blob: 4d61bb23a1046316e5e786821632fe02e1952c37 [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Serhiy Storchaka6716d602014-07-30 19:19:21 +030012 Only Tcl/Tk 8.4 and later are supported. Older versions are not
13 supported. Use Python 3.4 or older if you cannot upgrade your
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000014 Tcl/Tk libraries.
Guido van Rossuma80649b2000-03-28 20:07:05 +000015*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Serhiy Storchaka26861b02015-02-16 20:52:17 +020024#define PY_SSIZE_T_CLEAN
Guido van Rossum35d43371997-08-02 00:09:09 +000025
Guido van Rossum9722ad81995-09-22 23:49:28 +000026#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000027#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000028
Guido van Rossum00d93061998-05-28 23:06:38 +000029#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000030#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000031#endif
32
Guido van Rossum2a5119b1998-05-29 01:28:40 +000033#ifdef MS_WINDOWS
34#include <windows.h>
35#endif
36
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030037#define CHECK_SIZE(size, elemsize) \
Serhiy Storchaka26861b02015-02-16 20:52:17 +020038 ((size_t)(size) <= Py_MIN((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030039
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000040/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
41 it always; if Tcl is not threaded, the thread functions in
42 Tcl are empty. */
43#define TCL_THREADS
44
Jack Jansencb852442001-12-09 23:15:56 +000045#ifdef TK_FRAMEWORK
46#include <Tcl/tcl.h>
47#include <Tk/tk.h>
48#else
Guido van Rossum18468821994-06-20 07:49:28 +000049#include <tcl.h>
50#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000051#endif
Guido van Rossum18468821994-06-20 07:49:28 +000052
Guilherme Polo2d87e422009-04-10 22:19:09 +000053#include "tkinter.h"
54
Serhiy Storchaka71b49dd2015-04-22 10:59:32 +030055#if TK_HEX_VERSION < 0x08040200
Serhiy Storchaka6716d602014-07-30 19:19:21 +030056#error "Tk older than 8.4 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000057#endif
58
Serhiy Storchaka3af7a382015-04-22 10:53:08 +030059#if TK_HEX_VERSION >= 0x08050208 && TK_HEX_VERSION < 0x08060000 || \
60 TK_HEX_VERSION >= 0x08060200
Serhiy Storchakaea134da2015-04-02 18:46:50 +030061#define HAVE_LIBTOMMAMTH
62#include <tclTomMath.h>
63#endif
64
Jack Janseneddc1442003-11-20 01:44:59 +000065#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000066#define HAVE_CREATEFILEHANDLER
67#endif
68
Guido van Rossum00d93061998-05-28 23:06:38 +000069#ifdef HAVE_CREATEFILEHANDLER
70
Neal Norwitzd948a432006-01-08 01:08:55 +000071/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
72 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
73#ifndef TCL_UNIX_FD
74# ifdef TCL_WIN_SOCKET
75# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
76# else
77# define TCL_UNIX_FD 1
78# endif
79#endif
80
Guido van Rossum00d93061998-05-28 23:06:38 +000081/* Tcl_CreateFileHandler() changed several times; these macros deal with the
82 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
83 Unix, only because Jack added it back); when available on Windows, it only
84 applies to sockets. */
85
Guido van Rossum7bf15641998-05-22 18:28:17 +000086#ifdef MS_WINDOWS
87#define FHANDLETYPE TCL_WIN_SOCKET
88#else
89#define FHANDLETYPE TCL_UNIX_FD
90#endif
91
Guido van Rossum00d93061998-05-28 23:06:38 +000092/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
93 which uses this to handle Tcl events while the user is typing commands. */
94
95#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +000096#define WAIT_FOR_STDIN
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#endif /* HAVE_CREATEFILEHANDLER */
100
Guido van Rossumad4db171998-06-13 13:56:28 +0000101#ifdef MS_WINDOWS
102#include <conio.h>
103#define WAIT_FOR_STDIN
104#endif
105
Guido van Rossum00d93061998-05-28 23:06:38 +0000106#ifdef WITH_THREAD
107
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000108/* The threading situation is complicated. Tcl is not thread-safe, except
109 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000110
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300111 So we need to use a lock around all uses of Tcl. Previously, the
112 Python interpreter lock was used for this. However, this causes
113 problems when other Python threads need to run while Tcl is blocked
114 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000115
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300116 To solve this problem, a separate lock for Tcl is introduced.
117 Holding it is incompatible with holding Python's interpreter lock.
118 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000119
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300120 ENTER_TCL and LEAVE_TCL are brackets, just like
121 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
122 used whenever a call into Tcl is made that could call an event
123 handler, or otherwise affect the state of a Tcl interpreter. These
124 assume that the surrounding code has the Python interpreter lock;
125 inside the brackets, the Python interpreter lock has been released
126 and the lock for Tcl has been acquired.
127
128 Sometimes, it is necessary to have both the Python lock and the Tcl
129 lock. (For example, when transferring data from the Tcl
130 interpreter result to a Python string object.) This can be done by
131 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
132 reacquires the Python lock (and restores the thread state) but
133 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
134 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000135
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000136 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300137 handlers when the handler needs to use Python. Such event handlers
138 are entered while the lock for Tcl is held; the event handler
139 presumably needs to use Python. ENTER_PYTHON releases the lock for
140 Tcl and acquires the Python interpreter lock, restoring the
141 appropriate thread state, and LEAVE_PYTHON releases the Python
142 interpreter lock and re-acquires the lock for Tcl. It is okay for
143 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
144 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000145
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300146 These locks expand to several statements and brackets; they should
147 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000148
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300149 If Tcl is threaded, this approach won't work anymore. The Tcl
150 interpreter is only valid in the thread that created it, and all Tk
151 activity must happen in this thread, also. That means that the
152 mainloop must be invoked in the thread that created the
153 interpreter. Invoking commands from other threads is possible;
154 _tkinter will queue an event for the interpreter thread, which will
155 then execute the command and pass back the result. If the main
156 thread is not in the mainloop, and invoking commands causes an
157 exception; if the main loop is running but not processing events,
158 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000159
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300160 In addition, for a threaded Tcl, a single global tcl_tstate won't
161 be sufficient anymore, since multiple Tcl interpreters may
162 simultaneously dispatch in different threads. So we use the Tcl TLS
163 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000164
Guido van Rossum00d93061998-05-28 23:06:38 +0000165*/
166
Guido van Rossum65d5b571998-12-21 19:32:43 +0000167static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000168
169#ifdef TCL_THREADS
170static Tcl_ThreadDataKey state_key;
171typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300172#define tcl_tstate \
173 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000174#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000175static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000176#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000177
178#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000179 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
180 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000181
182#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300183 tcl_tstate = NULL; \
184 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000185
Guido van Rossum62320c91998-06-15 04:36:09 +0000186#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000187 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000188
189#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000190 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000191
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000192#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000193 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300194 if(tcl_lock) \
195 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000196
197#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 { PyThreadState *tstate = PyEval_SaveThread(); \
199 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000200
201#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000202 if (((TkappObject *)self)->threaded && \
203 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300204 PyErr_SetString(PyExc_RuntimeError, \
205 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000206 return 0; \
207 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000208
209#else
210
211#define ENTER_TCL
212#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000213#define ENTER_OVERLAP
214#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000215#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000216#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000217#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000218
219#endif
220
Guido van Rossum97867b21996-08-08 19:09:53 +0000221#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000222#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000223#endif
224
Guido van Rossum18468821994-06-20 07:49:28 +0000225/**** Tkapp Object Declaration ****/
226
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300227static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000228
Guido van Rossum00d93061998-05-28 23:06:38 +0000229typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000230 PyObject_HEAD
231 Tcl_Interp *interp;
232 int wantobjects;
233 int threaded; /* True if tcl_platform[threaded] */
234 Tcl_ThreadId thread_id;
235 int dispatching;
236 /* We cannot include tclInt.h, as this is internal.
237 So we cache interesting types here. */
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200238 const Tcl_ObjType *OldBooleanType;
Zachary Ware037605b2014-08-05 11:54:34 -0500239 const Tcl_ObjType *BooleanType;
240 const Tcl_ObjType *ByteArrayType;
241 const Tcl_ObjType *DoubleType;
242 const Tcl_ObjType *IntType;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300243 const Tcl_ObjType *WideIntType;
244 const Tcl_ObjType *BignumType;
Zachary Ware037605b2014-08-05 11:54:34 -0500245 const Tcl_ObjType *ListType;
246 const Tcl_ObjType *ProcBodyType;
247 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000248} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000249
Guido van Rossum18468821994-06-20 07:49:28 +0000250#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000251#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000252
Guido van Rossum35d43371997-08-02 00:09:09 +0000253#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000254(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000255
Barry Warsawfa701a81997-01-16 00:15:11 +0000256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000257
Guido van Rossum18468821994-06-20 07:49:28 +0000258/**** Error Handling ****/
259
260static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000261static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000262static int errorInCmd = 0;
263static PyObject *excInCmd;
264static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000265static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000266
Guilherme Polob681df42009-02-09 22:33:59 +0000267#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000268static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000269#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000271
Guido van Rossum18468821994-06-20 07:49:28 +0000272static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000273Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000274{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
276 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000277}
278
Barry Warsawfa701a81997-01-16 00:15:11 +0000279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000280
Guido van Rossum18468821994-06-20 07:49:28 +0000281/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000282
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000283static int Tkinter_busywaitinterval = 20;
284
Guido van Rossum00d93061998-05-28 23:06:38 +0000285#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000286#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000287
Guido van Rossum00d93061998-05-28 23:06:38 +0000288/* Millisecond sleep() for Unix platforms. */
289
290static void
Fred Drake509d79a2000-07-08 04:04:38 +0000291Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000292{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000293 /* XXX Too bad if you don't have select(). */
294 struct timeval t;
295 t.tv_sec = milli/1000;
296 t.tv_usec = (milli%1000) * 1000;
297 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000298}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000299#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000300
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000301/* Wait up to 1s for the mainloop to come up. */
302
303static int
304WaitForMainloop(TkappObject* self)
305{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000306 int i;
307 for (i = 0; i < 10; i++) {
308 if (self->dispatching)
309 return 1;
310 Py_BEGIN_ALLOW_THREADS
311 Sleep(100);
312 Py_END_ALLOW_THREADS
313 }
314 if (self->dispatching)
315 return 1;
316 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
317 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000318}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000319#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000321
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000322
Guido van Rossum18468821994-06-20 07:49:28 +0000323#define ARGSZ 64
324
Barry Warsawfa701a81997-01-16 00:15:11 +0000325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326
Guido van Rossum18468821994-06-20 07:49:28 +0000327static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200328unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
329{
330 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
331 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
332 /* Tcl encodes null character as \xc0\x80 */
333 if (memchr(s, '\xc0', size)) {
334 char *buf, *q;
335 const char *e = s + size;
336 PyErr_Clear();
337 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300338 if (buf == NULL) {
339 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200340 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300341 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200342 while (s != e) {
343 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
344 *q++ = '\0';
345 s += 2;
346 }
347 else
348 *q++ = *s++;
349 }
350 s = buf;
351 size = q - s;
352 r = PyUnicode_DecodeUTF8(s, size, NULL);
353 PyMem_Free(buf);
354 }
355 }
356 return r;
357}
358
359static PyObject *
360unicodeFromTclString(const char *s)
361{
362 return unicodeFromTclStringAndSize(s, strlen(s));
363}
364
365static PyObject *
366unicodeFromTclObj(Tcl_Obj *value)
367{
368 int len;
369 char *s = Tcl_GetStringFromObj(value, &len);
370 return unicodeFromTclStringAndSize(s, len);
371}
372
373
374static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300375Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000376{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000377 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300378 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000379 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000380
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000381 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300382 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000383 }
Guido van Rossum18468821994-06-20 07:49:28 +0000384
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000385 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
386 /* Not a list.
387 * Could be a quoted string containing funnies, e.g. {"}.
388 * Return the string itself.
389 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200390 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000391 }
Guido van Rossum18468821994-06-20 07:49:28 +0000392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000393 if (argc == 0)
394 v = PyUnicode_FromString("");
395 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200396 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000397 else if ((v = PyTuple_New(argc)) != NULL) {
398 int i;
399 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000401 for (i = 0; i < argc; i++) {
402 if ((w = Split(argv[i])) == NULL) {
403 Py_DECREF(v);
404 v = NULL;
405 break;
406 }
407 PyTuple_SetItem(v, i, w);
408 }
409 }
410 Tcl_Free(FREECAST argv);
411 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000412}
413
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300414/* In some cases, Tcl will still return strings that are supposed to
415 be lists. SplitObj walks through a nested tuple, finding string
416 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000417
Martin v. Löwis59683e82008-06-13 07:50:45 +0000418static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000419SplitObj(PyObject *arg)
420{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000421 if (PyTuple_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200422 Py_ssize_t i, size;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000424
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000425 size = PyTuple_Size(arg);
426 result = NULL;
427 /* Recursively invoke SplitObj for all tuple items.
428 If this does not return a new object, no action is
429 needed. */
430 for(i = 0; i < size; i++) {
431 elem = PyTuple_GetItem(arg, i);
432 newelem = SplitObj(elem);
433 if (!newelem) {
434 Py_XDECREF(result);
435 return NULL;
436 }
437 if (!result) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200438 Py_ssize_t k;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000439 if (newelem == elem) {
440 Py_DECREF(newelem);
441 continue;
442 }
443 result = PyTuple_New(size);
444 if (!result)
445 return NULL;
446 for(k = 0; k < i; k++) {
447 elem = PyTuple_GetItem(arg, k);
448 Py_INCREF(elem);
449 PyTuple_SetItem(result, k, elem);
450 }
451 }
452 PyTuple_SetItem(result, i, newelem);
453 }
454 if (result)
455 return result;
456 /* Fall through, returning arg. */
457 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300458 else if (PyList_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200459 Py_ssize_t i, size;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300460 PyObject *elem, *newelem, *result;
461
462 size = PyList_GET_SIZE(arg);
463 result = PyTuple_New(size);
464 if (!result)
465 return NULL;
466 /* Recursively invoke SplitObj for all list items. */
467 for(i = 0; i < size; i++) {
468 elem = PyList_GET_ITEM(arg, i);
469 newelem = SplitObj(elem);
470 if (!newelem) {
471 Py_XDECREF(result);
472 return NULL;
473 }
474 PyTuple_SetItem(result, i, newelem);
475 }
476 return result;
477 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300478 else if (PyUnicode_Check(arg)) {
479 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300480 const char **argv;
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300481 char *list = PyUnicode_AsUTF8(arg);
482
483 if (list == NULL ||
484 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
485 Py_INCREF(arg);
486 return arg;
487 }
488 Tcl_Free(FREECAST argv);
489 if (argc > 1)
490 return Split(list);
491 /* Fall through, returning arg. */
492 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000493 else if (PyBytes_Check(arg)) {
494 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300495 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000496 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000497
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000498 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
499 Py_INCREF(arg);
500 return arg;
501 }
502 Tcl_Free(FREECAST argv);
503 if (argc > 1)
504 return Split(PyBytes_AsString(arg));
505 /* Fall through, returning arg. */
506 }
507 Py_INCREF(arg);
508 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000509}
Barry Warsawfa701a81997-01-16 00:15:11 +0000510
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000511
Guido van Rossum18468821994-06-20 07:49:28 +0000512/**** Tkapp Object ****/
513
514#ifndef WITH_APPINIT
515int
Fred Drake509d79a2000-07-08 04:04:38 +0000516Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000517{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000518 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000519
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000520 if (Tcl_Init(interp) == TCL_ERROR) {
521 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
522 return TCL_ERROR;
523 }
Guilherme Polob681df42009-02-09 22:33:59 +0000524
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000525 _tkinter_skip_tk_init = Tcl_GetVar(interp,
526 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
527 if (_tkinter_skip_tk_init != NULL &&
528 strcmp(_tkinter_skip_tk_init, "1") == 0) {
529 return TCL_OK;
530 }
Guilherme Polob681df42009-02-09 22:33:59 +0000531
532#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 if (tk_load_failed) {
534 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
535 return TCL_ERROR;
536 }
Guilherme Polob681df42009-02-09 22:33:59 +0000537#endif
538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000539 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000540#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000541 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000542#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000543 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
544 return TCL_ERROR;
545 }
Guilherme Polob681df42009-02-09 22:33:59 +0000546
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000548}
549#endif /* !WITH_APPINIT */
550
Guido van Rossum18468821994-06-20 07:49:28 +0000551
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000552
Barry Warsawfa701a81997-01-16 00:15:11 +0000553
554/* Initialize the Tk application; see the `main' function in
555 * `tkMain.c'.
556 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000557
Thomas Wouters58d05102000-07-24 14:43:35 +0000558static void EnableEventHook(void); /* Forward */
559static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000560
Barry Warsawfa701a81997-01-16 00:15:11 +0000561static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300562Tkapp_New(const char *screenName, const char *className,
563 int interactive, int wantobjects, int wantTk, int sync,
564 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000565{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000566 TkappObject *v;
567 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000568
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300569 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000570 if (v == NULL)
571 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200572 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000573
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000574 v->interp = Tcl_CreateInterp();
575 v->wantobjects = wantobjects;
576 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
577 TCL_GLOBAL_ONLY) != NULL;
578 v->thread_id = Tcl_GetCurrentThread();
579 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000580
581#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000582 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300583 PyErr_SetString(PyExc_RuntimeError,
584 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000585 Py_DECREF(v);
586 return 0;
587 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000588#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000589#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000590 if (v->threaded && tcl_lock) {
591 /* If Tcl is threaded, we don't need the lock. */
592 PyThread_free_lock(tcl_lock);
593 tcl_lock = NULL;
594 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000595#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000596
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200597 v->OldBooleanType = Tcl_GetObjType("boolean");
598 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000599 v->ByteArrayType = Tcl_GetObjType("bytearray");
600 v->DoubleType = Tcl_GetObjType("double");
601 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300602 v->WideIntType = Tcl_GetObjType("wideInt");
603 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000604 v->ListType = Tcl_GetObjType("list");
605 v->ProcBodyType = Tcl_GetObjType("procbody");
606 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000607
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000608 /* Delete the 'exit' command, which can screw things up */
609 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000611 if (screenName != NULL)
612 Tcl_SetVar2(v->interp, "env", "DISPLAY",
613 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000614
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000615 if (interactive)
616 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
617 else
618 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000619
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000620 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200621 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000622 if (!argv0) {
623 PyErr_NoMemory();
624 Py_DECREF(v);
625 return NULL;
626 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000628 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200629 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
630 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000631 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200632 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000634 if (! wantTk) {
635 Tcl_SetVar(v->interp,
636 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
637 }
Guilherme Polob681df42009-02-09 22:33:59 +0000638#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639 else if (tk_load_failed) {
640 Tcl_SetVar(v->interp,
641 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
642 }
Guilherme Polob681df42009-02-09 22:33:59 +0000643#endif
David Aschere2b4b322004-02-18 05:59:53 +0000644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 /* some initial arguments need to be in argv */
646 if (sync || use) {
647 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200648 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 if (sync)
651 len += sizeof "-sync";
652 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200653 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000654
Victor Stinneree6c3c72014-09-11 17:50:21 +0200655 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000656 if (!args) {
657 PyErr_NoMemory();
658 Py_DECREF(v);
659 return NULL;
660 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000661
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 args[0] = '\0';
663 if (sync)
664 strcat(args, "-sync");
665 if (use) {
666 if (sync)
667 strcat(args, " ");
668 strcat(args, "-use ");
669 strcat(args, use);
670 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000672 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200673 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 if (Tcl_AppInit(v->interp) != TCL_OK) {
677 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000678#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000679 if (wantTk) {
680 const char *_tkinter_tk_failed;
681 _tkinter_tk_failed = Tcl_GetVar(v->interp,
682 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 if ( _tkinter_tk_failed != NULL &&
685 strcmp(_tkinter_tk_failed, "1") == 0) {
686 tk_load_failed = 1;
687 }
688 }
Guilherme Polob681df42009-02-09 22:33:59 +0000689#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 Py_DECREF((PyObject *)v);
691 return (TkappObject *)result;
692 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000696 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000697}
698
Barry Warsawfa701a81997-01-16 00:15:11 +0000699
Benjamin Peterson5879d412009-03-30 14:51:56 +0000700#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000701static void
702Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000703 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000704{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000705 Py_BEGIN_ALLOW_THREADS;
706 Tcl_MutexLock(mutex);
707 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
708 Tcl_ThreadAlert(self->thread_id);
709 Tcl_ConditionWait(cond, mutex, NULL);
710 Tcl_MutexUnlock(mutex);
711 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000712}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000713#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000714
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000715
Guido van Rossum18468821994-06-20 07:49:28 +0000716/** Tcl Eval **/
717
Martin v. Löwisffad6332002-11-26 09:28:05 +0000718typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000719 PyObject_HEAD
720 Tcl_Obj *value;
721 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000722} PyTclObject;
723
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300724static PyObject *PyTclObject_Type;
725#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000726
727static PyObject *
728newPyTclObject(Tcl_Obj *arg)
729{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000730 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300731 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000732 if (self == NULL)
733 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200734 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000735 Tcl_IncrRefCount(arg);
736 self->value = arg;
737 self->string = NULL;
738 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000739}
740
741static void
742PyTclObject_dealloc(PyTclObject *self)
743{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200744 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000745 Tcl_DecrRefCount(self->value);
746 Py_XDECREF(self->string);
747 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200748 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000749}
750
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000751static char*
752PyTclObject_TclString(PyObject *self)
753{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000755}
756
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000757/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000758PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000759"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000760
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000761static PyObject *
762PyTclObject_string(PyTclObject *self, void *ignored)
763{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000764 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200765 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000766 if (!self->string)
767 return NULL;
768 }
769 Py_INCREF(self->string);
770 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000771}
772
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000773static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000774PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000775{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200776 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000777 Py_INCREF(self->string);
778 return self->string;
779 }
780 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200781 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000782}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000783
Martin v. Löwisffad6332002-11-26 09:28:05 +0000784static PyObject *
785PyTclObject_repr(PyTclObject *self)
786{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300787 PyObject *repr, *str = PyTclObject_str(self, NULL);
788 if (str == NULL)
789 return NULL;
790 repr = PyUnicode_FromFormat("<%s object: %R>",
791 self->value->typePtr->name, str);
792 Py_DECREF(str);
793 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000794}
795
Mark Dickinson211c6252009-02-01 10:28:51 +0000796#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
797
798static PyObject *
799PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000800{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000801 int result;
802 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000803
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000804 /* neither argument should be NULL, unless something's gone wrong */
805 if (self == NULL || other == NULL) {
806 PyErr_BadInternalCall();
807 return NULL;
808 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000809
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000810 /* both arguments should be instances of PyTclObject */
811 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
812 v = Py_NotImplemented;
813 goto finished;
814 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000815
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000816 if (self == other)
817 /* fast path when self and other are identical */
818 result = 0;
819 else
820 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
821 Tcl_GetString(((PyTclObject *)other)->value));
822 /* Convert return value to a Boolean */
823 switch (op) {
824 case Py_EQ:
825 v = TEST_COND(result == 0);
826 break;
827 case Py_NE:
828 v = TEST_COND(result != 0);
829 break;
830 case Py_LE:
831 v = TEST_COND(result <= 0);
832 break;
833 case Py_GE:
834 v = TEST_COND(result >= 0);
835 break;
836 case Py_LT:
837 v = TEST_COND(result < 0);
838 break;
839 case Py_GT:
840 v = TEST_COND(result > 0);
841 break;
842 default:
843 PyErr_BadArgument();
844 return NULL;
845 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000846 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000847 Py_INCREF(v);
848 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000849}
850
Martin v. Löwis39195712003-01-04 00:33:13 +0000851PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
852
Martin v. Löwisffad6332002-11-26 09:28:05 +0000853static PyObject*
854get_typename(PyTclObject* obj, void* ignored)
855{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200856 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000857}
858
Martin v. Löwis39195712003-01-04 00:33:13 +0000859
Martin v. Löwisffad6332002-11-26 09:28:05 +0000860static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000861 {"typename", (getter)get_typename, NULL, get_typename__doc__},
862 {"string", (getter)PyTclObject_string, NULL,
863 PyTclObject_string__doc__},
864 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000865};
866
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300867static PyType_Slot PyTclObject_Type_slots[] = {
868 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
869 {Py_tp_repr, (reprfunc)PyTclObject_repr},
870 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200871 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300872 {Py_tp_richcompare, PyTclObject_richcompare},
873 {Py_tp_getset, PyTclObject_getsetlist},
874 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000875};
876
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300877static PyType_Spec PyTclObject_Type_spec = {
878 "_tkinter.Tcl_Obj",
879 sizeof(PyTclObject),
880 0,
881 Py_TPFLAGS_DEFAULT,
882 PyTclObject_Type_slots,
883};
884
885
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300886#if PY_SIZE_MAX > INT_MAX
887#define CHECK_STRING_LENGTH(s) do { \
888 if (s != NULL && strlen(s) >= INT_MAX) { \
889 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
890 return NULL; \
891 } } while(0)
892#else
893#define CHECK_STRING_LENGTH(s)
894#endif
895
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300896#ifdef HAVE_LIBTOMMAMTH
897static Tcl_Obj*
898asBignumObj(PyObject *value)
899{
900 Tcl_Obj *result;
901 int neg;
902 PyObject *hexstr;
903 char *hexchars;
904 mp_int bigValue;
905
906 neg = Py_SIZE(value) < 0;
907 hexstr = _PyLong_Format(value, 16);
908 if (hexstr == NULL)
909 return NULL;
910 hexchars = PyUnicode_AsUTF8(hexstr);
911 if (hexchars == NULL) {
912 Py_DECREF(hexstr);
913 return NULL;
914 }
915 hexchars += neg + 2; /* skip sign and "0x" */
916 mp_init(&bigValue);
917 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
918 mp_clear(&bigValue);
919 Py_DECREF(hexstr);
920 PyErr_NoMemory();
921 return NULL;
922 }
923 Py_DECREF(hexstr);
924 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
925 result = Tcl_NewBignumObj(&bigValue);
926 mp_clear(&bigValue);
927 if (result == NULL) {
928 PyErr_NoMemory();
929 return NULL;
930 }
931 return result;
932}
933#endif
934
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000935static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000936AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000937{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000938 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000939
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200940 if (PyBytes_Check(value)) {
941 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
942 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
943 return NULL;
944 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300945 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200946 (int)PyBytes_GET_SIZE(value));
947 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300948
949 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000950 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300951
952 if (PyLong_CheckExact(value)) {
953 int overflow;
954 long longValue;
955#ifdef TCL_WIDE_INT_TYPE
956 Tcl_WideInt wideValue;
957#endif
958 longValue = PyLong_AsLongAndOverflow(value, &overflow);
959 if (!overflow) {
960 return Tcl_NewLongObj(longValue);
961 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000962 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300963 fall through to wideInt handling. */
964#ifdef TCL_WIDE_INT_TYPE
965 if (_PyLong_AsByteArray((PyLongObject *)value,
966 (unsigned char *)(void *)&wideValue,
967 sizeof(wideValue),
968 PY_LITTLE_ENDIAN,
969 /* signed */ 1) == 0) {
970 return Tcl_NewWideIntObj(wideValue);
971 }
972 PyErr_Clear();
973#endif
974 /* If there is an overflow in the wideInt conversion,
975 fall through to bignum handling. */
976#ifdef HAVE_LIBTOMMAMTH
977 return asBignumObj(value);
978#endif
979 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000980 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000981 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300982
983 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000984 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300985
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +0300986 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300987 Tcl_Obj **argv;
988 Py_ssize_t size, i;
989
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300990 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300991 if (size == 0)
992 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300993 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300994 PyErr_SetString(PyExc_OverflowError,
995 PyTuple_Check(value) ? "tuple is too long" :
996 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300997 return NULL;
998 }
Victor Stinneree6c3c72014-09-11 17:50:21 +0200999 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
1000 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001001 PyErr_NoMemory();
1002 return NULL;
1003 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001004 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001005 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001006 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001007 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001008 return result;
1009 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001010
1011 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001012 void *inbuf;
1013 Py_ssize_t size;
1014 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001015 Tcl_UniChar *outbuf = NULL;
1016 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001017 size_t allocsize;
1018
1019 if (PyUnicode_READY(value) == -1)
1020 return NULL;
1021
1022 inbuf = PyUnicode_DATA(value);
1023 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001024 if (size == 0)
1025 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001026 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1027 PyErr_SetString(PyExc_OverflowError, "string is too long");
1028 return NULL;
1029 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001030 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001031 if (kind == sizeof(Tcl_UniChar))
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001032 return Tcl_NewUnicodeObj(inbuf, (int)size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001033 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001034 outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001035 /* Else overflow occurred, and we take the next exit */
1036 if (!outbuf) {
1037 PyErr_NoMemory();
1038 return NULL;
1039 }
1040 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001041 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1042 /* We cannot test for sizeof(Tcl_UniChar) directly,
1043 so we test for UTF-8 size instead. */
1044#if TCL_UTF_MAX == 3
1045 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001046 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001047 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001048 "character U+%x is above the range "
1049 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001050 ch);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001051 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001052 return NULL;
1053 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001054#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001055 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001056 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001057 result = Tcl_NewUnicodeObj(outbuf, (int)size);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001058 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001059 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001060 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001061
1062 if (PyTclObject_Check(value)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001063 Tcl_Obj *v = ((PyTclObject*)value)->value;
1064 Tcl_IncrRefCount(v);
1065 return v;
1066 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001067
1068 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001069 PyObject *v = PyObject_Str(value);
1070 if (!v)
1071 return 0;
1072 result = AsObj(v);
1073 Py_DECREF(v);
1074 return result;
1075 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001076}
1077
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001078static PyObject *
1079fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1080{
1081 int boolValue;
1082 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1083 return Tkinter_Error(tkapp);
1084 return PyBool_FromLong(boolValue);
1085}
1086
Martin v. Löwisffad6332002-11-26 09:28:05 +00001087static PyObject*
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001088fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1089{
1090 Tcl_WideInt wideValue;
1091 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
1092#ifdef HAVE_LONG_LONG
1093 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1094 return PyLong_FromLongLong(wideValue);
1095#endif
1096 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1097 sizeof(wideValue),
1098 PY_LITTLE_ENDIAN,
1099 /* signed */ 1);
1100 }
1101 return NULL;
1102}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001103
1104#ifdef HAVE_LIBTOMMAMTH
1105static PyObject*
1106fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1107{
1108 mp_int bigValue;
1109 unsigned long numBytes;
1110 unsigned char *bytes;
1111 PyObject *res;
1112
1113 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1114 return Tkinter_Error(tkapp);
1115 numBytes = mp_unsigned_bin_size(&bigValue);
1116 bytes = PyMem_Malloc(numBytes);
1117 if (bytes == NULL) {
1118 mp_clear(&bigValue);
1119 return PyErr_NoMemory();
1120 }
1121 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1122 &numBytes) != MP_OKAY) {
1123 mp_clear(&bigValue);
1124 PyMem_Free(bytes);
1125 return PyErr_NoMemory();
1126 }
1127 res = _PyLong_FromByteArray(bytes, numBytes,
1128 /* big-endian */ 0,
1129 /* unsigned */ 0);
1130 PyMem_Free(bytes);
1131 if (res != NULL && bigValue.sign == MP_NEG) {
1132 PyObject *res2 = PyNumber_Negative(res);
1133 Py_DECREF(res);
1134 res = res2;
1135 }
1136 mp_clear(&bigValue);
1137 return res;
1138}
1139#endif
1140
Martin v. Löwisffad6332002-11-26 09:28:05 +00001141static PyObject*
1142FromObj(PyObject* tkapp, Tcl_Obj *value)
1143{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001144 PyObject *result = NULL;
1145 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001146 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001147
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001148 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001149 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001150 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001151
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001152 if (value->typePtr == app->BooleanType ||
1153 value->typePtr == app->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001154 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001155 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001156
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001157 if (value->typePtr == app->ByteArrayType) {
1158 int size;
1159 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1160 return PyBytes_FromStringAndSize(data, size);
1161 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001162
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001163 if (value->typePtr == app->DoubleType) {
1164 return PyFloat_FromDouble(value->internalRep.doubleValue);
1165 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001166
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001167 if (value->typePtr == app->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001168 long longValue;
1169 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1170 return PyLong_FromLong(longValue);
1171 /* If there is an error in the long conversion,
1172 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001173 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001174
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001175 if (value->typePtr == app->IntType ||
1176 value->typePtr == app->WideIntType) {
1177 result = fromWideIntObj(tkapp, value);
1178 if (result != NULL || PyErr_Occurred())
1179 return result;
1180 Tcl_ResetResult(interp);
1181 /* If there is an error in the wideInt conversion,
1182 fall through to bignum handling. */
1183 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001184
1185#ifdef HAVE_LIBTOMMAMTH
1186 if (value->typePtr == app->IntType ||
1187 value->typePtr == app->WideIntType ||
1188 value->typePtr == app->BignumType) {
1189 return fromBignumObj(tkapp, value);
1190 }
1191#endif
1192
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001193 if (value->typePtr == app->ListType) {
1194 int size;
1195 int i, status;
1196 PyObject *elem;
1197 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001198
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001199 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001200 if (status == TCL_ERROR)
1201 return Tkinter_Error(tkapp);
1202 result = PyTuple_New(size);
1203 if (!result)
1204 return NULL;
1205 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001206 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001207 if (status == TCL_ERROR) {
1208 Py_DECREF(result);
1209 return Tkinter_Error(tkapp);
1210 }
1211 elem = FromObj(tkapp, tcl_elem);
1212 if (!elem) {
1213 Py_DECREF(result);
1214 return NULL;
1215 }
1216 PyTuple_SetItem(result, i, elem);
1217 }
1218 return result;
1219 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001220
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001221 if (value->typePtr == app->ProcBodyType) {
1222 /* fall through: return tcl object. */
1223 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001224
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001225 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001226 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001227 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001228 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001229 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001230
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001231#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001232 if (app->BooleanType == NULL &&
1233 strcmp(value->typePtr->name, "booleanString") == 0) {
1234 /* booleanString type is not registered in Tcl */
1235 app->BooleanType = value->typePtr;
1236 return fromBoolean(tkapp, value);
1237 }
1238#endif
1239
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001240#ifdef HAVE_LIBTOMMAMTH
1241 if (app->BignumType == NULL &&
1242 strcmp(value->typePtr->name, "bignum") == 0) {
1243 /* bignum type is not registered in Tcl */
1244 app->BignumType = value->typePtr;
1245 return fromBignumObj(tkapp, value);
1246 }
1247#endif
1248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001249 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001250}
1251
Benjamin Peterson5879d412009-03-30 14:51:56 +00001252#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001253/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001254TCL_DECLARE_MUTEX(call_mutex)
1255
1256typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001257 Tcl_Event ev; /* Must be first */
1258 TkappObject *self;
1259 PyObject *args;
1260 int flags;
1261 PyObject **res;
1262 PyObject **exc_type, **exc_value, **exc_tb;
1263 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001264} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001265#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001266
1267void
1268Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001269{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001270 int i;
1271 for (i = 0; i < objc; i++)
1272 Tcl_DecrRefCount(objv[i]);
1273 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001274 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001275}
Guido van Rossum18468821994-06-20 07:49:28 +00001276
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001277/* Convert Python objects to Tcl objects. This must happen in the
1278 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001279
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001280static Tcl_Obj**
1281Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1282{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001283 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001284 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001285 if (args == NULL)
1286 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001287
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001288 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001289 objv[0] = AsObj(args);
1290 if (objv[0] == 0)
1291 goto finally;
1292 objc = 1;
1293 Tcl_IncrRefCount(objv[0]);
1294 }
1295 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001296 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001298 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001299 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001300 PyErr_SetString(PyExc_OverflowError,
1301 PyTuple_Check(args) ? "tuple is too long" :
1302 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001303 return NULL;
1304 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001305 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001306 if (objv == NULL) {
1307 PyErr_NoMemory();
1308 objc = 0;
1309 goto finally;
1310 }
1311 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001313 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001314 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 if (v == Py_None) {
1316 objc = i;
1317 break;
1318 }
1319 objv[i] = AsObj(v);
1320 if (!objv[i]) {
1321 /* Reset objc, so it attempts to clear
1322 objects only up to i. */
1323 objc = i;
1324 goto finally;
1325 }
1326 Tcl_IncrRefCount(objv[i]);
1327 }
1328 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001329 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001330 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001331finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001332 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001333 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001334}
Guido van Rossum212643f1998-04-29 16:22:14 +00001335
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001336/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001337
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001338static PyObject*
1339Tkapp_CallResult(TkappObject *self)
1340{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001341 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001342 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001344 /* Not sure whether the IncrRef is necessary, but something
1345 may overwrite the interpreter result while we are
1346 converting it. */
1347 Tcl_IncrRefCount(value);
1348 res = FromObj((PyObject*)self, value);
1349 Tcl_DecrRefCount(value);
1350 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001351 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 }
1353 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001354}
Guido van Rossum632de272000-03-29 00:19:50 +00001355
Benjamin Peterson5879d412009-03-30 14:51:56 +00001356#ifdef WITH_THREAD
1357
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001358/* Tkapp_CallProc is the event procedure that is executed in the context of
1359 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1360 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001361
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001362static int
1363Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1364{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001365 Tcl_Obj *objStore[ARGSZ];
1366 Tcl_Obj **objv;
1367 int objc;
1368 int i;
1369 ENTER_PYTHON
1370 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1371 if (!objv) {
1372 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1373 *(e->res) = NULL;
1374 }
1375 LEAVE_PYTHON
1376 if (!objv)
1377 goto done;
1378 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1379 ENTER_PYTHON
1380 if (i == TCL_ERROR) {
1381 *(e->res) = NULL;
1382 *(e->exc_type) = NULL;
1383 *(e->exc_tb) = NULL;
1384 *(e->exc_value) = PyObject_CallFunction(
1385 Tkinter_TclError, "s",
1386 Tcl_GetStringResult(e->self->interp));
1387 }
1388 else {
1389 *(e->res) = Tkapp_CallResult(e->self);
1390 }
1391 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001393 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001394done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001395 /* Wake up calling thread. */
1396 Tcl_MutexLock(&call_mutex);
1397 Tcl_ConditionNotify(e->done);
1398 Tcl_MutexUnlock(&call_mutex);
1399 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001400}
1401
Benjamin Peterson5879d412009-03-30 14:51:56 +00001402#endif
1403
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001404/* This is the main entry point for calling a Tcl command.
1405 It supports three cases, with regard to threading:
1406 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1407 the context of the calling thread.
1408 2. Tcl is threaded, caller of the command is in the interpreter thread:
1409 Execute the command in the calling thread. Since the Tcl lock will
1410 not be used, we can merge that with case 1.
1411 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1412 the interpreter thread. Allocation of Tcl objects needs to occur in the
1413 interpreter thread, so we ship the PyObject* args to the target thread,
1414 and perform processing there. */
1415
1416static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001417Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001418{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001419 Tcl_Obj *objStore[ARGSZ];
1420 Tcl_Obj **objv = NULL;
1421 int objc, i;
1422 PyObject *res = NULL;
1423 TkappObject *self = (TkappObject*)selfptr;
1424 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001426 /* If args is a single tuple, replace with contents of tuple */
1427 if (1 == PyTuple_Size(args)){
1428 PyObject* item = PyTuple_GetItem(args, 0);
1429 if (PyTuple_Check(item))
1430 args = item;
1431 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001432#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001433 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1434 /* We cannot call the command directly. Instead, we must
1435 marshal the parameters to the interpreter thread. */
1436 Tkapp_CallEvent *ev;
1437 Tcl_Condition cond = NULL;
1438 PyObject *exc_type, *exc_value, *exc_tb;
1439 if (!WaitForMainloop(self))
1440 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001441 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1442 if (ev == NULL) {
1443 PyErr_NoMemory();
1444 return NULL;
1445 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001446 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1447 ev->self = self;
1448 ev->args = args;
1449 ev->res = &res;
1450 ev->exc_type = &exc_type;
1451 ev->exc_value = &exc_value;
1452 ev->exc_tb = &exc_tb;
1453 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001454
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001455 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001456
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001457 if (res == NULL) {
1458 if (exc_type)
1459 PyErr_Restore(exc_type, exc_value, exc_tb);
1460 else
1461 PyErr_SetObject(Tkinter_TclError, exc_value);
1462 }
1463 Tcl_ConditionFinalize(&cond);
1464 }
1465 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001466#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001467 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001469 objv = Tkapp_CallArgs(args, objStore, &objc);
1470 if (!objv)
1471 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001473 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001475 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001477 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001478
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001479 if (i == TCL_ERROR)
1480 Tkinter_Error(selfptr);
1481 else
1482 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001486 Tkapp_CallDeallocArgs(objv, objStore, objc);
1487 }
1488 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001489}
1490
1491
1492static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001493Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001494{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001495 char *script;
1496 PyObject *res = NULL;
1497 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001498
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001499 if (!PyArg_ParseTuple(args, "s:eval", &script))
1500 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001501
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001502 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001503 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001504
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001505 ENTER_TCL
1506 err = Tcl_Eval(Tkapp_Interp(self), script);
1507 ENTER_OVERLAP
1508 if (err == TCL_ERROR)
1509 res = Tkinter_Error(self);
1510 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001511 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001512 LEAVE_OVERLAP_TCL
1513 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001514}
1515
1516static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001517Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001518{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001519 char *fileName;
1520 PyObject *res = NULL;
1521 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001522
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001523 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1524 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001525
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001526 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001527 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001529 ENTER_TCL
1530 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1531 ENTER_OVERLAP
1532 if (err == TCL_ERROR)
1533 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001534 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001535 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001536 LEAVE_OVERLAP_TCL
1537 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001538}
1539
1540static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001541Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001542{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001543 char *script;
1544 PyObject *res = NULL;
1545 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001546
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001547 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001548 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001549
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001550 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001551 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001552
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001553 ENTER_TCL
1554 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1555 ENTER_OVERLAP
1556 if (err == TCL_ERROR)
1557 res = Tkinter_Error(self);
1558 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001559 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001560 LEAVE_OVERLAP_TCL
1561 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001562}
1563
1564static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001565Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001566{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001567 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001568
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001569 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1570 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001571 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001572 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001573
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001574 ENTER_TCL
1575 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1576 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001577
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001578 Py_RETURN_NONE;
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 +00001583/** Tcl Variable **/
1584
Benjamin Peterson5879d412009-03-30 14:51:56 +00001585typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1586
1587#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001588TCL_DECLARE_MUTEX(var_mutex)
1589
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001590typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001591 Tcl_Event ev; /* must be first */
1592 PyObject *self;
1593 PyObject *args;
1594 int flags;
1595 EventFunc func;
1596 PyObject **res;
1597 PyObject **exc_type;
1598 PyObject **exc_val;
1599 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001600} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001601#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001602
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001603static int
1604varname_converter(PyObject *in, void *_out)
1605{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001606 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001607 char **out = (char**)_out;
1608 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001609 if (PyBytes_Size(in) > INT_MAX) {
1610 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1611 return 0;
1612 }
1613 s = PyBytes_AsString(in);
Victor Stinner706768c2014-08-16 01:03:39 +02001614 if (strlen(s) != (size_t)PyBytes_Size(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001615 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001616 return 0;
1617 }
1618 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001619 return 1;
1620 }
1621 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001622 Py_ssize_t size;
1623 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001624 if (s == NULL) {
1625 return 0;
1626 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001627 if (size > INT_MAX) {
1628 PyErr_SetString(PyExc_OverflowError, "string is too long");
1629 return 0;
1630 }
Victor Stinner706768c2014-08-16 01:03:39 +02001631 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001632 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001633 return 0;
1634 }
1635 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001636 return 1;
1637 }
1638 if (PyTclObject_Check(in)) {
1639 *out = PyTclObject_TclString(in);
1640 return 1;
1641 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001642 PyErr_Format(PyExc_TypeError,
1643 "must be str, bytes or Tcl_Obj, not %.50s",
1644 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001645 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001646}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001647
Benjamin Peterson5879d412009-03-30 14:51:56 +00001648#ifdef WITH_THREAD
1649
Martin v. Löwis59683e82008-06-13 07:50:45 +00001650static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001651var_perform(VarEvent *ev)
1652{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001653 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1654 if (!*(ev->res)) {
1655 PyObject *exc, *val, *tb;
1656 PyErr_Fetch(&exc, &val, &tb);
1657 PyErr_NormalizeException(&exc, &val, &tb);
1658 *(ev->exc_type) = exc;
1659 *(ev->exc_val) = val;
1660 Py_DECREF(tb);
1661 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001662
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001663}
1664
1665static int
1666var_proc(VarEvent* ev, int flags)
1667{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001668 ENTER_PYTHON
1669 var_perform(ev);
1670 Tcl_MutexLock(&var_mutex);
1671 Tcl_ConditionNotify(ev->cond);
1672 Tcl_MutexUnlock(&var_mutex);
1673 LEAVE_PYTHON
1674 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001675}
1676
Benjamin Peterson5879d412009-03-30 14:51:56 +00001677#endif
1678
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001679static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001680var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001681{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001682#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001683 TkappObject *self = (TkappObject*)selfptr;
1684 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001685 VarEvent *ev;
1686 PyObject *res, *exc_type, *exc_val;
1687 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001688
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001689 /* The current thread is not the interpreter thread. Marshal
1690 the call to the interpreter thread, then wait for
1691 completion. */
1692 if (!WaitForMainloop(self))
1693 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001694
Serhiy Storchaka07940882014-09-11 10:38:54 +03001695 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1696 if (ev == NULL) {
1697 PyErr_NoMemory();
1698 return NULL;
1699 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001700 ev->self = selfptr;
1701 ev->args = args;
1702 ev->flags = flags;
1703 ev->func = func;
1704 ev->res = &res;
1705 ev->exc_type = &exc_type;
1706 ev->exc_val = &exc_val;
1707 ev->cond = &cond;
1708 ev->ev.proc = (Tcl_EventProc*)var_proc;
1709 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1710 Tcl_ConditionFinalize(&cond);
1711 if (!res) {
1712 PyErr_SetObject(exc_type, exc_val);
1713 Py_DECREF(exc_type);
1714 Py_DECREF(exc_val);
1715 return NULL;
1716 }
1717 return res;
1718 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001719#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001720 /* Tcl is not threaded, or this is the interpreter thread. */
1721 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001722}
1723
Guido van Rossum18468821994-06-20 07:49:28 +00001724static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001725SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001726{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001727 char *name1, *name2;
1728 PyObject *newValue;
1729 PyObject *res = NULL;
1730 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001731
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001732 switch (PyTuple_GET_SIZE(args)) {
1733 case 2:
1734 if (!PyArg_ParseTuple(args, "O&O:setvar",
1735 varname_converter, &name1, &newValue))
1736 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001737 /* XXX Acquire tcl lock??? */
1738 newval = AsObj(newValue);
1739 if (newval == NULL)
1740 return NULL;
1741 ENTER_TCL
1742 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1743 newval, flags);
1744 ENTER_OVERLAP
1745 if (!ok)
1746 Tkinter_Error(self);
1747 else {
1748 res = Py_None;
1749 Py_INCREF(res);
1750 }
1751 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001752 break;
1753 case 3:
1754 if (!PyArg_ParseTuple(args, "ssO:setvar",
1755 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001756 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001757 CHECK_STRING_LENGTH(name1);
1758 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001759 /* XXX must hold tcl lock already??? */
1760 newval = AsObj(newValue);
1761 ENTER_TCL
1762 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1763 ENTER_OVERLAP
1764 if (!ok)
1765 Tkinter_Error(self);
1766 else {
1767 res = Py_None;
1768 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001769 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001770 LEAVE_OVERLAP_TCL
1771 break;
1772 default:
1773 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1774 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 }
1776 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001777}
1778
1779static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001780Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001781{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001782 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001783}
1784
1785static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001786Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001787{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001788 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001789}
1790
Barry Warsawfa701a81997-01-16 00:15:11 +00001791
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001792
Guido van Rossum18468821994-06-20 07:49:28 +00001793static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001794GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001795{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001796 char *name1, *name2=NULL;
1797 PyObject *res = NULL;
1798 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001799
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001800 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1801 varname_converter, &name1, &name2))
1802 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001803
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001804 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001805 ENTER_TCL
1806 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1807 ENTER_OVERLAP
1808 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001809 PyErr_SetString(Tkinter_TclError,
1810 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001811 } else {
1812 if (((TkappObject*)self)->wantobjects) {
1813 res = FromObj(self, tres);
1814 }
1815 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001816 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001817 }
1818 }
1819 LEAVE_OVERLAP_TCL
1820 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001821}
1822
1823static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001824Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001825{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001826 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001827}
1828
1829static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001830Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001831{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001832 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001833}
1834
Barry Warsawfa701a81997-01-16 00:15:11 +00001835
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001836
Guido van Rossum18468821994-06-20 07:49:28 +00001837static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001838UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001839{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001840 char *name1, *name2=NULL;
1841 int code;
1842 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001844 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1845 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001846
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001847 CHECK_STRING_LENGTH(name1);
1848 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001849 ENTER_TCL
1850 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1851 ENTER_OVERLAP
1852 if (code == TCL_ERROR)
1853 res = Tkinter_Error(self);
1854 else {
1855 Py_INCREF(Py_None);
1856 res = Py_None;
1857 }
1858 LEAVE_OVERLAP_TCL
1859 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001860}
1861
1862static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001863Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001864{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001865 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001866}
1867
1868static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001869Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001870{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001871 return var_invoke(UnsetVar, self, args,
1872 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001873}
1874
Barry Warsawfa701a81997-01-16 00:15:11 +00001875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001876
Guido van Rossum18468821994-06-20 07:49:28 +00001877/** Tcl to Python **/
1878
1879static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001880Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001881{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001882 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001883 Tcl_Obj *value;
1884 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00001885
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001886 if (PyTuple_Size(args) == 1) {
1887 PyObject* o = PyTuple_GetItem(args, 0);
1888 if (PyLong_Check(o)) {
1889 Py_INCREF(o);
1890 return o;
1891 }
1892 }
1893 if (!PyArg_ParseTuple(args, "s:getint", &s))
1894 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001895 CHECK_STRING_LENGTH(s);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001896 value = Tcl_NewStringObj(s, -1);
1897 if (value == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001898 return Tkinter_Error(self);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001899 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
1900 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
1901
1902 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
1903 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
1904 */
1905#ifdef HAVE_LIBTOMMAMTH
1906 result = fromBignumObj(self, value);
1907#else
1908 result = fromWideIntObj(self, value);
1909#endif
1910 Tcl_DecrRefCount(value);
1911 if (result != NULL || PyErr_Occurred())
1912 return result;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001913 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001914}
1915
1916static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001917Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001918{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001919 char *s;
1920 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001921
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001922 if (PyTuple_Size(args) == 1) {
1923 PyObject *o = PyTuple_GetItem(args, 0);
1924 if (PyFloat_Check(o)) {
1925 Py_INCREF(o);
1926 return o;
1927 }
1928 }
1929 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1930 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001931 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001932 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1933 return Tkinter_Error(self);
1934 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001935}
1936
1937static PyObject *
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03001938Tkapp_GetBoolean(PyObject *self, PyObject *arg)
Guido van Rossum18468821994-06-20 07:49:28 +00001939{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001940 char *s;
1941 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001942
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03001943 if (PyLong_Check(arg)) { /* int or bool */
1944 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001945 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03001946
1947 if (PyTclObject_Check(arg)) {
1948 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
1949 ((PyTclObject*)arg)->value,
1950 &v) == TCL_ERROR)
1951 return Tkinter_Error(self);
1952 return PyBool_FromLong(v);
1953 }
1954
1955 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001956 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001957 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001958 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1959 return Tkinter_Error(self);
1960 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001961}
1962
1963static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001964Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001965{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001966 char *s;
1967 PyObject *res = NULL;
1968 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001969
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001970 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1971 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001972
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001973 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001974 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001975
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001976 ENTER_TCL
1977 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1978 ENTER_OVERLAP
1979 if (retval == TCL_ERROR)
1980 res = Tkinter_Error(self);
1981 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001982 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001983 LEAVE_OVERLAP_TCL
1984 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001985}
1986
1987static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001988Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001989{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001990 char *s;
1991 PyObject *res = NULL;
1992 int retval;
1993 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001994
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001995 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1996 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001997
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001998 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001999 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002000
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002001 ENTER_TCL
2002 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2003 ENTER_OVERLAP
2004 if (retval == TCL_ERROR)
2005 res = Tkinter_Error(self);
2006 else
2007 res = Py_BuildValue("l", v);
2008 LEAVE_OVERLAP_TCL
2009 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002010}
2011
2012static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002013Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002014{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002015 char *s;
2016 PyObject *res = NULL;
2017 double v;
2018 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002019
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002020 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2021 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002022 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002023 CHECK_TCL_APPARTMENT;
2024 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2025 ENTER_TCL
2026 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2027 ENTER_OVERLAP
2028 PyFPE_END_PROTECT(retval)
2029 if (retval == TCL_ERROR)
2030 res = Tkinter_Error(self);
2031 else
2032 res = Py_BuildValue("d", v);
2033 LEAVE_OVERLAP_TCL
2034 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002035}
2036
2037static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002038Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002039{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002040 char *s;
2041 PyObject *res = NULL;
2042 int retval;
2043 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002044
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002045 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2046 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002047 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002048 CHECK_TCL_APPARTMENT;
2049 ENTER_TCL
2050 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2051 ENTER_OVERLAP
2052 if (retval == TCL_ERROR)
2053 res = Tkinter_Error(self);
2054 else
2055 res = Py_BuildValue("i", v);
2056 LEAVE_OVERLAP_TCL
2057 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002058}
2059
Barry Warsawfa701a81997-01-16 00:15:11 +00002060
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002061
Guido van Rossum18468821994-06-20 07:49:28 +00002062static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002063Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002064{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002065 char *list;
2066 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002067 const char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002068 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002069 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002070
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002071 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2072 return NULL;
2073 if (PyTclObject_Check(arg)) {
2074 int objc;
2075 Tcl_Obj **objv;
2076 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2077 ((PyTclObject*)arg)->value,
2078 &objc, &objv) == TCL_ERROR) {
2079 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002080 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002081 if (!(v = PyTuple_New(objc)))
2082 return NULL;
2083 for (i = 0; i < objc; i++) {
2084 PyObject *s = FromObj(self, objv[i]);
2085 if (!s || PyTuple_SetItem(v, i, s)) {
2086 Py_DECREF(v);
2087 return NULL;
2088 }
2089 }
2090 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002091 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002092 if (PyTuple_Check(arg)) {
2093 Py_INCREF(arg);
2094 return arg;
2095 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002096 if (PyList_Check(arg)) {
2097 return PySequence_Tuple(arg);
2098 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002099
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002100 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2101 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002102
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002103 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002104 if (Tcl_SplitList(Tkapp_Interp(self), list,
2105 &argc, &argv) == TCL_ERROR) {
2106 PyMem_Free(list);
2107 return Tkinter_Error(self);
2108 }
Guido van Rossum18468821994-06-20 07:49:28 +00002109
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002110 if (!(v = PyTuple_New(argc)))
2111 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002112
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002113 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002114 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115 if (!s || PyTuple_SetItem(v, i, s)) {
2116 Py_DECREF(v);
2117 v = NULL;
2118 goto finally;
2119 }
2120 }
Guido van Rossum18468821994-06-20 07:49:28 +00002121
Barry Warsawfa701a81997-01-16 00:15:11 +00002122 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002123 ckfree(FREECAST argv);
2124 PyMem_Free(list);
2125 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002126}
2127
2128static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002129Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002130{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002131 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002132 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002133
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002134 if (!PyArg_ParseTuple(args, "O:split", &arg))
2135 return NULL;
2136 if (PyTclObject_Check(arg)) {
2137 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2138 int objc;
2139 Tcl_Obj **objv;
2140 int i;
2141 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2142 &objc, &objv) == TCL_ERROR) {
2143 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002144 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002145 if (objc == 0)
2146 return PyUnicode_FromString("");
2147 if (objc == 1)
2148 return FromObj(self, objv[0]);
2149 if (!(v = PyTuple_New(objc)))
2150 return NULL;
2151 for (i = 0; i < objc; i++) {
2152 PyObject *s = FromObj(self, objv[i]);
2153 if (!s || PyTuple_SetItem(v, i, s)) {
2154 Py_DECREF(v);
2155 return NULL;
2156 }
2157 }
2158 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002159 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002160 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002161 return SplitObj(arg);
2162
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002163 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2164 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002165 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002166 v = Split(list);
2167 PyMem_Free(list);
2168 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002169}
2170
Barry Warsawfa701a81997-01-16 00:15:11 +00002171
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002172
Guido van Rossum18468821994-06-20 07:49:28 +00002173/** Tcl Command **/
2174
Guido van Rossum00d93061998-05-28 23:06:38 +00002175/* Client data struct */
2176typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002177 PyObject *self;
2178 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002179} PythonCmd_ClientData;
2180
2181static int
Fred Drake509d79a2000-07-08 04:04:38 +00002182PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002183{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002184 errorInCmd = 1;
2185 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2186 LEAVE_PYTHON
2187 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002188}
2189
Guido van Rossum18468821994-06-20 07:49:28 +00002190/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002191 * function or method.
2192 */
Guido van Rossum18468821994-06-20 07:49:28 +00002193static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002194PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002195{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002196 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002197 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002198 int i, rv;
2199 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002200
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002201 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002202
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002203 /* TBD: no error checking here since we know, via the
2204 * Tkapp_CreateCommand() that the client data is a two-tuple
2205 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002206 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002207
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002208 /* Create argument list (argv1, ..., argvN) */
2209 if (!(arg = PyTuple_New(argc - 1)))
2210 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002212 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002213 PyObject *s = unicodeFromTclString(argv[i + 1]);
2214 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002215 Py_DECREF(arg);
2216 return PythonCmd_Error(interp);
2217 }
2218 }
2219 res = PyEval_CallObject(func, arg);
2220 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002221
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002222 if (res == NULL)
2223 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002224
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002225 obj_res = AsObj(res);
2226 if (obj_res == NULL) {
2227 Py_DECREF(res);
2228 return PythonCmd_Error(interp);
2229 }
2230 else {
2231 Tcl_SetObjResult(interp, obj_res);
2232 rv = TCL_OK;
2233 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002234
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002235 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002236
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002237 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002239 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002240}
2241
2242static void
Fred Drake509d79a2000-07-08 04:04:38 +00002243PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002244{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002245 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002246
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002247 ENTER_PYTHON
2248 Py_XDECREF(data->self);
2249 Py_XDECREF(data->func);
2250 PyMem_DEL(data);
2251 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002252}
2253
Barry Warsawfa701a81997-01-16 00:15:11 +00002254
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002255
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002256
Benjamin Peterson5879d412009-03-30 14:51:56 +00002257#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002258TCL_DECLARE_MUTEX(command_mutex)
2259
2260typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002261 Tcl_Event ev;
2262 Tcl_Interp* interp;
2263 char *name;
2264 int create;
2265 int *status;
2266 ClientData *data;
2267 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002268} CommandEvent;
2269
2270static int
2271Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002272{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002273 if (ev->create)
2274 *ev->status = Tcl_CreateCommand(
2275 ev->interp, ev->name, PythonCmd,
2276 ev->data, PythonCmdDelete) == NULL;
2277 else
2278 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2279 Tcl_MutexLock(&command_mutex);
2280 Tcl_ConditionNotify(ev->done);
2281 Tcl_MutexUnlock(&command_mutex);
2282 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002283}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002284#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002285
2286static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002287Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002288{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002289 TkappObject *self = (TkappObject*)selfptr;
2290 PythonCmd_ClientData *data;
2291 char *cmdName;
2292 PyObject *func;
2293 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002294
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002295 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2296 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002297 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002298 if (!PyCallable_Check(func)) {
2299 PyErr_SetString(PyExc_TypeError, "command not callable");
2300 return NULL;
2301 }
Guido van Rossum18468821994-06-20 07:49:28 +00002302
Martin v. Löwisa9656492003-03-30 08:44:58 +00002303#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002304 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2305 !WaitForMainloop(self))
2306 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002307#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002308
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002309 data = PyMem_NEW(PythonCmd_ClientData, 1);
2310 if (!data)
2311 return PyErr_NoMemory();
2312 Py_INCREF(self);
2313 Py_INCREF(func);
2314 data->self = selfptr;
2315 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002316#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002317 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2318 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002319 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2320 if (ev == NULL) {
2321 PyErr_NoMemory();
2322 PyMem_DEL(data);
2323 return NULL;
2324 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002325 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2326 ev->interp = self->interp;
2327 ev->create = 1;
2328 ev->name = cmdName;
2329 ev->data = (ClientData)data;
2330 ev->status = &err;
2331 ev->done = &cond;
2332 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2333 Tcl_ConditionFinalize(&cond);
2334 }
2335 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002336#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002337 {
2338 ENTER_TCL
2339 err = Tcl_CreateCommand(
2340 Tkapp_Interp(self), cmdName, PythonCmd,
2341 (ClientData)data, PythonCmdDelete) == NULL;
2342 LEAVE_TCL
2343 }
2344 if (err) {
2345 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2346 PyMem_DEL(data);
2347 return NULL;
2348 }
Guido van Rossum18468821994-06-20 07:49:28 +00002349
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002350 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002351}
2352
Barry Warsawfa701a81997-01-16 00:15:11 +00002353
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002354
Guido van Rossum18468821994-06-20 07:49:28 +00002355static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002356Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002357{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002358 TkappObject *self = (TkappObject*)selfptr;
2359 char *cmdName;
2360 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002362 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2363 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002364 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002365
2366#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002367 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2368 Tcl_Condition cond = NULL;
2369 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002370 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2371 if (ev == NULL) {
2372 PyErr_NoMemory();
2373 return NULL;
2374 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002375 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2376 ev->interp = self->interp;
2377 ev->create = 0;
2378 ev->name = cmdName;
2379 ev->status = &err;
2380 ev->done = &cond;
2381 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2382 &command_mutex);
2383 Tcl_ConditionFinalize(&cond);
2384 }
2385 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002386#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002387 {
2388 ENTER_TCL
2389 err = Tcl_DeleteCommand(self->interp, cmdName);
2390 LEAVE_TCL
2391 }
2392 if (err == -1) {
2393 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2394 return NULL;
2395 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002396 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002397}
2398
Barry Warsawfa701a81997-01-16 00:15:11 +00002399
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002400
Guido van Rossum00d93061998-05-28 23:06:38 +00002401#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002402/** File Handler **/
2403
Guido van Rossum00d93061998-05-28 23:06:38 +00002404typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002405 PyObject *func;
2406 PyObject *file;
2407 int id;
2408 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002409} FileHandler_ClientData;
2410
2411static FileHandler_ClientData *HeadFHCD;
2412
2413static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002414NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002415{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002416 FileHandler_ClientData *p;
2417 p = PyMem_NEW(FileHandler_ClientData, 1);
2418 if (p != NULL) {
2419 Py_XINCREF(func);
2420 Py_XINCREF(file);
2421 p->func = func;
2422 p->file = file;
2423 p->id = id;
2424 p->next = HeadFHCD;
2425 HeadFHCD = p;
2426 }
2427 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002428}
2429
2430static void
Fred Drake509d79a2000-07-08 04:04:38 +00002431DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002432{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002433 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002434
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002435 pp = &HeadFHCD;
2436 while ((p = *pp) != NULL) {
2437 if (p->id == id) {
2438 *pp = p->next;
2439 Py_XDECREF(p->func);
2440 Py_XDECREF(p->file);
2441 PyMem_DEL(p);
2442 }
2443 else
2444 pp = &p->next;
2445 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002446}
2447
Guido van Rossuma597dde1995-01-10 20:56:29 +00002448static void
Fred Drake509d79a2000-07-08 04:04:38 +00002449FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002450{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002451 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2452 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002454 ENTER_PYTHON
2455 func = data->func;
2456 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002457
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002458 arg = Py_BuildValue("(Oi)", file, (long) mask);
2459 res = PyEval_CallObject(func, arg);
2460 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002462 if (res == NULL) {
2463 errorInCmd = 1;
2464 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2465 }
2466 Py_XDECREF(res);
2467 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002468}
2469
Guido van Rossum18468821994-06-20 07:49:28 +00002470static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002471Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2472 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002473{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002474 FileHandler_ClientData *data;
2475 PyObject *file, *func;
2476 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002477
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002478 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2479 &file, &mask, &func))
2480 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002481
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002482 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002484 tfile = PyObject_AsFileDescriptor(file);
2485 if (tfile < 0)
2486 return NULL;
2487 if (!PyCallable_Check(func)) {
2488 PyErr_SetString(PyExc_TypeError, "bad argument list");
2489 return NULL;
2490 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002491
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002492 data = NewFHCD(func, file, tfile);
2493 if (data == NULL)
2494 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002495
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002496 /* Ought to check for null Tcl_File object... */
2497 ENTER_TCL
2498 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2499 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002500 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002501}
2502
2503static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002504Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002505{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002506 PyObject *file;
2507 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002508
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002509 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2510 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002512 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002513
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002514 tfile = PyObject_AsFileDescriptor(file);
2515 if (tfile < 0)
2516 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002517
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002518 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002519
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002520 /* Ought to check for null Tcl_File object... */
2521 ENTER_TCL
2522 Tcl_DeleteFileHandler(tfile);
2523 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002524 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002525}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002526#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002527
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002528
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002529/**** Tktt Object (timer token) ****/
2530
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002531static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002532
Guido van Rossum00d93061998-05-28 23:06:38 +00002533typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002534 PyObject_HEAD
2535 Tcl_TimerToken token;
2536 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002537} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002538
2539static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002540Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002541{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002542 TkttObject *v = (TkttObject *)self;
2543 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002544
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002545 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2546 return NULL;
2547 if (v->token != NULL) {
2548 Tcl_DeleteTimerHandler(v->token);
2549 v->token = NULL;
2550 }
2551 if (func != NULL) {
2552 v->func = NULL;
2553 Py_DECREF(func);
2554 Py_DECREF(v); /* See Tktt_New() */
2555 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002556 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002557}
2558
2559static PyMethodDef Tktt_methods[] =
2560{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002561 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2562 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002563};
2564
2565static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002566Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002567{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002568 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002569
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002570 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002571 if (v == NULL)
2572 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002573 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002574
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002575 Py_INCREF(func);
2576 v->token = NULL;
2577 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579 /* Extra reference, deleted when called or when handler is deleted */
2580 Py_INCREF(v);
2581 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002582}
2583
2584static void
Fred Drake509d79a2000-07-08 04:04:38 +00002585Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002586{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002587 TkttObject *v = (TkttObject *)self;
2588 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002589 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002590
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002591 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002593 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002594 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002595}
2596
Guido van Rossum597ac201998-05-12 14:36:19 +00002597static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002598Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002599{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002600 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002601 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2602 v,
2603 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002604}
2605
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002606static PyType_Slot Tktt_Type_slots[] = {
2607 {Py_tp_dealloc, Tktt_Dealloc},
2608 {Py_tp_repr, Tktt_Repr},
2609 {Py_tp_methods, Tktt_methods},
2610 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002611};
2612
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002613static PyType_Spec Tktt_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002614 "_tkinter.tktimertoken",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002615 sizeof(TkttObject),
2616 0,
2617 Py_TPFLAGS_DEFAULT,
2618 Tktt_Type_slots,
2619};
Barry Warsawfa701a81997-01-16 00:15:11 +00002620
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002621
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002622/** Timer Handler **/
2623
2624static void
Fred Drake509d79a2000-07-08 04:04:38 +00002625TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002626{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002627 TkttObject *v = (TkttObject *)clientData;
2628 PyObject *func = v->func;
2629 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002631 if (func == NULL)
2632 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002634 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002635
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002636 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002637
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002638 res = PyEval_CallObject(func, NULL);
2639 Py_DECREF(func);
2640 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002641
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002642 if (res == NULL) {
2643 errorInCmd = 1;
2644 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2645 }
2646 else
2647 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002648
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002649 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002650}
2651
2652static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002653Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002654{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002655 int milliseconds;
2656 PyObject *func;
2657 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002659 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2660 &milliseconds, &func))
2661 return NULL;
2662 if (!PyCallable_Check(func)) {
2663 PyErr_SetString(PyExc_TypeError, "bad argument list");
2664 return NULL;
2665 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002667 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002669 v = Tktt_New(func);
2670 if (v) {
2671 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2672 (ClientData)v);
2673 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002674
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002675 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002676}
2677
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002678
Guido van Rossum18468821994-06-20 07:49:28 +00002679/** Event Loop **/
2680
Guido van Rossum18468821994-06-20 07:49:28 +00002681static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002682Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002683{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002684 int threshold = 0;
2685 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002686#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002687 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002688#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002689
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002690 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2691 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002692
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002693 CHECK_TCL_APPARTMENT;
2694 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002696 quitMainLoop = 0;
2697 while (Tk_GetNumMainWindows() > threshold &&
2698 !quitMainLoop &&
2699 !errorInCmd)
2700 {
2701 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002702
2703#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002704 if (self->threaded) {
2705 /* Allow other Python threads to run. */
2706 ENTER_TCL
2707 result = Tcl_DoOneEvent(0);
2708 LEAVE_TCL
2709 }
2710 else {
2711 Py_BEGIN_ALLOW_THREADS
2712 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2713 tcl_tstate = tstate;
2714 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2715 tcl_tstate = NULL;
2716 if(tcl_lock)PyThread_release_lock(tcl_lock);
2717 if (result == 0)
2718 Sleep(Tkinter_busywaitinterval);
2719 Py_END_ALLOW_THREADS
2720 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002721#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002722 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002723#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002724
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002725 if (PyErr_CheckSignals() != 0) {
2726 self->dispatching = 0;
2727 return NULL;
2728 }
2729 if (result < 0)
2730 break;
2731 }
2732 self->dispatching = 0;
2733 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002734
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002735 if (errorInCmd) {
2736 errorInCmd = 0;
2737 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2738 excInCmd = valInCmd = trbInCmd = NULL;
2739 return NULL;
2740 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002741 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002742}
2743
2744static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002745Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002746{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002747 int flags = 0;
2748 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002749
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002750 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2751 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002752
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002753 ENTER_TCL
2754 rv = Tcl_DoOneEvent(flags);
2755 LEAVE_TCL
2756 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002757}
2758
2759static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002760Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002761{
2762
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002763 if (!PyArg_ParseTuple(args, ":quit"))
2764 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002765
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002766 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002767 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002768}
2769
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002770static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002771Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002772{
2773
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002774 if (!PyArg_ParseTuple(args, ":interpaddr"))
2775 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002776
Victor Stinnere1040e22013-09-05 00:22:24 +02002777 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002778}
2779
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002780static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002781Tkapp_TkInit(PyObject *self, PyObject *args)
2782{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002783 Tcl_Interp *interp = Tkapp_Interp(self);
2784 const char * _tk_exists = NULL;
2785 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002786
Guilherme Polob681df42009-02-09 22:33:59 +00002787#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002788 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2789 * first call failed.
2790 * To avoid the deadlock, we just refuse the second call through
2791 * a static variable.
2792 */
2793 if (tk_load_failed) {
2794 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2795 return NULL;
2796 }
Guilherme Polob681df42009-02-09 22:33:59 +00002797#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002798
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002799 /* We want to guard against calling Tk_Init() multiple times */
2800 CHECK_TCL_APPARTMENT;
2801 ENTER_TCL
2802 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2803 ENTER_OVERLAP
2804 if (err == TCL_ERROR) {
2805 /* This sets an exception, but we cannot return right
2806 away because we need to exit the overlap first. */
2807 Tkinter_Error(self);
2808 } else {
2809 _tk_exists = Tkapp_Result(self);
2810 }
2811 LEAVE_OVERLAP_TCL
2812 if (err == TCL_ERROR) {
2813 return NULL;
2814 }
2815 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2816 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002817 PyErr_SetString(Tkinter_TclError,
2818 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002819#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002820 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002821#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002822 return NULL;
2823 }
2824 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002825 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002826}
Barry Warsawfa701a81997-01-16 00:15:11 +00002827
Martin v. Löwisffad6332002-11-26 09:28:05 +00002828static PyObject *
2829Tkapp_WantObjects(PyObject *self, PyObject *args)
2830{
2831
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002832 int wantobjects = -1;
2833 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2834 return NULL;
2835 if (wantobjects == -1)
2836 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2837 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002838
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002839 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002840}
2841
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002842static PyObject *
2843Tkapp_WillDispatch(PyObject *self, PyObject *args)
2844{
2845
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002846 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002847
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002848 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002849}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002850
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002851
Guido van Rossum18468821994-06-20 07:49:28 +00002852/**** Tkapp Method List ****/
2853
2854static PyMethodDef Tkapp_methods[] =
2855{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002856 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2857 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2858 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002859 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002860 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2861 {"record", Tkapp_Record, METH_VARARGS},
2862 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2863 {"setvar", Tkapp_SetVar, METH_VARARGS},
2864 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2865 {"getvar", Tkapp_GetVar, METH_VARARGS},
2866 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2867 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2868 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2869 {"getint", Tkapp_GetInt, METH_VARARGS},
2870 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002871 {"getboolean", Tkapp_GetBoolean, METH_O},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002872 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2873 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2874 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2875 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2876 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2877 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002878 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2879 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002880#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002881 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2882 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002883#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002884 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2885 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2886 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2887 {"quit", Tkapp_Quit, METH_VARARGS},
2888 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2889 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2890 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002891};
2892
Barry Warsawfa701a81997-01-16 00:15:11 +00002893
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002894
Guido van Rossum18468821994-06-20 07:49:28 +00002895/**** Tkapp Type Methods ****/
2896
2897static void
Fred Drake509d79a2000-07-08 04:04:38 +00002898Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002899{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002900 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002901 /*CHECK_TCL_APPARTMENT;*/
2902 ENTER_TCL
2903 Tcl_DeleteInterp(Tkapp_Interp(self));
2904 LEAVE_TCL
2905 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002906 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002907 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002908}
2909
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002910static PyType_Slot Tkapp_Type_slots[] = {
2911 {Py_tp_dealloc, Tkapp_Dealloc},
2912 {Py_tp_methods, Tkapp_methods},
2913 {0, 0}
2914};
2915
2916
2917static PyType_Spec Tkapp_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002918 "_tkinter.tkapp",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002919 sizeof(TkappObject),
2920 0,
2921 Py_TPFLAGS_DEFAULT,
2922 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002923};
2924
Barry Warsawfa701a81997-01-16 00:15:11 +00002925
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002926
Guido van Rossum18468821994-06-20 07:49:28 +00002927/**** Tkinter Module ****/
2928
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002929typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002930 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002931 Py_ssize_t size; /* current size */
2932 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002933} FlattenContext;
2934
2935static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002936_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002937{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002938 /* expand tuple to hold (at least) size new items.
2939 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002940
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002941 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002942
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002943 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002944 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002945
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002946 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002947
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002948 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002949}
2950
2951static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002952_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002953{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002954 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002955
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002956 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002957
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002958 if (depth > 1000) {
2959 PyErr_SetString(PyExc_ValueError,
2960 "nesting too deep in _flatten");
2961 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002962 } else if (PyTuple_Check(item) || PyList_Check(item)) {
2963 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002964 /* preallocate (assume no nesting) */
2965 if (context->size + size > context->maxsize &&
2966 !_bump(context, size))
2967 return 0;
2968 /* copy items to output tuple */
2969 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002970 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002971 if (PyList_Check(o) || PyTuple_Check(o)) {
2972 if (!_flatten1(context, o, depth + 1))
2973 return 0;
2974 } else if (o != Py_None) {
2975 if (context->size + 1 > context->maxsize &&
2976 !_bump(context, 1))
2977 return 0;
2978 Py_INCREF(o);
2979 PyTuple_SET_ITEM(context->tuple,
2980 context->size++, o);
2981 }
2982 }
2983 } else {
2984 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2985 return 0;
2986 }
2987 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002988}
2989
2990static PyObject *
2991Tkinter_Flatten(PyObject* self, PyObject* args)
2992{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002993 FlattenContext context;
2994 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002995
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002996 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2997 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002998
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002999 context.maxsize = PySequence_Size(item);
3000 if (context.maxsize < 0)
3001 return NULL;
3002 if (context.maxsize == 0)
3003 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003004
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003005 context.tuple = PyTuple_New(context.maxsize);
3006 if (!context.tuple)
3007 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003008
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003009 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003010
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003011 if (!_flatten1(&context, item,0))
3012 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003013
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003014 if (_PyTuple_Resize(&context.tuple, context.size))
3015 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003016
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003017 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003018}
3019
Guido van Rossum18468821994-06-20 07:49:28 +00003020static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003021Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003022{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003023 char *screenName = NULL;
3024 char *baseName = NULL; /* XXX this is not used anymore;
3025 try getting rid of it. */
3026 char *className = NULL;
3027 int interactive = 0;
Serhiy Storchaka9e7cbda2014-05-28 16:57:55 +03003028 int wantobjects = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003029 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3030 int sync = 0; /* pass -sync to wish */
3031 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003032
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003033 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003034
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003035 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3036 &screenName, &baseName, &className,
3037 &interactive, &wantobjects, &wantTk,
3038 &sync, &use))
3039 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003040 CHECK_STRING_LENGTH(screenName);
3041 CHECK_STRING_LENGTH(baseName);
3042 CHECK_STRING_LENGTH(className);
3043 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003044
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003045 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003046 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003047 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003048}
3049
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003050static PyObject *
3051Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3052{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003053 int new_val;
3054 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3055 return NULL;
3056 if (new_val < 0) {
3057 PyErr_SetString(PyExc_ValueError,
3058 "busywaitinterval must be >= 0");
3059 return NULL;
3060 }
3061 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003062 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003063}
3064
3065static char setbusywaitinterval_doc[] =
3066"setbusywaitinterval(n) -> None\n\
3067\n\
3068Set the busy-wait interval in milliseconds between successive\n\
3069calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3070It should be set to a divisor of the maximum time between\n\
3071frames in an animation.";
3072
3073static PyObject *
3074Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3075{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003076 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003077}
3078
3079static char getbusywaitinterval_doc[] =
3080"getbusywaitinterval() -> int\n\
3081\n\
3082Return the current busy-wait interval between successive\n\
3083calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3084
Guido van Rossum18468821994-06-20 07:49:28 +00003085static PyMethodDef moduleMethods[] =
3086{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003087 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3088 {"create", Tkinter_Create, METH_VARARGS},
3089 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3090 setbusywaitinterval_doc},
3091 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3092 METH_NOARGS, getbusywaitinterval_doc},
3093 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003094};
3095
Guido van Rossum7bf15641998-05-22 18:28:17 +00003096#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003097
3098static int stdin_ready = 0;
3099
Guido van Rossumad4db171998-06-13 13:56:28 +00003100#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003101static void
Fred Drake509d79a2000-07-08 04:04:38 +00003102MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003103{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003104 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003105}
Guido van Rossumad4db171998-06-13 13:56:28 +00003106#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003107
Martin v. Löwisa9656492003-03-30 08:44:58 +00003108#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003109static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003110#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003111
Guido van Rossum18468821994-06-20 07:49:28 +00003112static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003113EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003114{
Guido van Rossumad4db171998-06-13 13:56:28 +00003115#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003116 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003117#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003118#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003119 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003120#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003121 stdin_ready = 0;
3122 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003123#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003124 tfile = fileno(stdin);
3125 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003126#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003127 while (!errorInCmd && !stdin_ready) {
3128 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003129#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003130 if (_kbhit()) {
3131 stdin_ready = 1;
3132 break;
3133 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003134#endif
3135#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003136 Py_BEGIN_ALLOW_THREADS
3137 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3138 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003139
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003140 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003141
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003142 tcl_tstate = NULL;
3143 if(tcl_lock)PyThread_release_lock(tcl_lock);
3144 if (result == 0)
3145 Sleep(Tkinter_busywaitinterval);
3146 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003147#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003148 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003149#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003150
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003151 if (result < 0)
3152 break;
3153 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003154#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003155 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003156#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003157 if (errorInCmd) {
3158 errorInCmd = 0;
3159 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3160 excInCmd = valInCmd = trbInCmd = NULL;
3161 PyErr_Print();
3162 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003163#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003164 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003165#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003166 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003167}
Guido van Rossum18468821994-06-20 07:49:28 +00003168
Guido van Rossum00d93061998-05-28 23:06:38 +00003169#endif
3170
Guido van Rossum7bf15641998-05-22 18:28:17 +00003171static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003172EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003173{
Guido van Rossum00d93061998-05-28 23:06:38 +00003174#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003175 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003176#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003177 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003178#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003179 PyOS_InputHook = EventHook;
3180 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003181#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003182}
3183
3184static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003185DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003186{
Guido van Rossum00d93061998-05-28 23:06:38 +00003187#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003188 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3189 PyOS_InputHook = NULL;
3190 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003191#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003192}
3193
Barry Warsawfa701a81997-01-16 00:15:11 +00003194
Martin v. Löwis1a214512008-06-11 05:26:20 +00003195static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003196 PyModuleDef_HEAD_INIT,
3197 "_tkinter",
3198 NULL,
3199 -1,
3200 moduleMethods,
3201 NULL,
3202 NULL,
3203 NULL,
3204 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003205};
3206
Mark Hammond62b1ab12002-07-23 06:31:15 +00003207PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003208PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003209{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003210 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003211
Guido van Rossum00d93061998-05-28 23:06:38 +00003212#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003213 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003214 if (tcl_lock == NULL)
3215 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003216#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003217
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003218 m = PyModule_Create(&_tkintermodule);
3219 if (m == NULL)
3220 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003221
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003222 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3223 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003224 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003225 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003226 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003227 Py_INCREF(o);
3228 if (PyModule_AddObject(m, "TclError", o)) {
3229 Py_DECREF(o);
3230 Py_DECREF(m);
3231 return NULL;
3232 }
3233 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003234
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003235 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3236 Py_DECREF(m);
3237 return NULL;
3238 }
3239 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3240 Py_DECREF(m);
3241 return NULL;
3242 }
3243 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3244 Py_DECREF(m);
3245 return NULL;
3246 }
3247 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3248 Py_DECREF(m);
3249 return NULL;
3250 }
3251 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3252 Py_DECREF(m);
3253 return NULL;
3254 }
3255 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3256 Py_DECREF(m);
3257 return NULL;
3258 }
3259 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3260 Py_DECREF(m);
3261 return NULL;
3262 }
3263 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3264 Py_DECREF(m);
3265 return NULL;
3266 }
3267 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3268 Py_DECREF(m);
3269 return NULL;
3270 }
3271 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3272 Py_DECREF(m);
3273 return NULL;
3274 }
3275 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3276 Py_DECREF(m);
3277 return NULL;
3278 }
3279
3280 o = PyType_FromSpec(&Tkapp_Type_spec);
3281 if (o == NULL) {
3282 Py_DECREF(m);
3283 return NULL;
3284 }
3285 if (PyModule_AddObject(m, "TkappType", o)) {
3286 Py_DECREF(o);
3287 Py_DECREF(m);
3288 return NULL;
3289 }
3290 Tkapp_Type = o;
3291
3292 o = PyType_FromSpec(&Tktt_Type_spec);
3293 if (o == NULL) {
3294 Py_DECREF(m);
3295 return NULL;
3296 }
3297 if (PyModule_AddObject(m, "TkttType", o)) {
3298 Py_DECREF(o);
3299 Py_DECREF(m);
3300 return NULL;
3301 }
3302 Tktt_Type = o;
3303
3304 o = PyType_FromSpec(&PyTclObject_Type_spec);
3305 if (o == NULL) {
3306 Py_DECREF(m);
3307 return NULL;
3308 }
3309 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3310 Py_DECREF(o);
3311 Py_DECREF(m);
3312 return NULL;
3313 }
3314 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003315
3316#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003317 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3318 * start waking up. Note that Tcl_FindExecutable will do this, this
3319 * code must be above it! The original warning from
3320 * tkMacOSXAppInit.c is copied below.
3321 *
3322 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3323 * Tcl interpreter for now. It probably should work to do this
3324 * in the other order, but for now it doesn't seem to.
3325 *
3326 */
3327 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003328#endif
3329
3330
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003331 /* This helps the dynamic loader; in Unicode aware Tcl versions
3332 it also helps Tcl find its encodings. */
3333 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3334 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003335 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003336 if (cexe)
3337 Tcl_FindExecutable(PyBytes_AsString(cexe));
3338 Py_XDECREF(cexe);
3339 Py_DECREF(uexe);
3340 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003341
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003342 if (PyErr_Occurred()) {
3343 Py_DECREF(m);
3344 return NULL;
3345 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003346
Guido van Rossum43ff8681998-07-14 18:02:13 +00003347#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003348 /* This was not a good idea; through <Destroy> bindings,
3349 Tcl_Finalize() may invoke Python code but at that point the
3350 interpreter and thread state have already been destroyed! */
3351 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003352#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003353 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003354}