blob: 1f21c0398372447bdc92f3dda8b0395ff3852ab7 [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
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +0300512/*[clinic input]
513module _tkinter
514class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec"
515class _tkinter.Tcl_Obj "PyTclObject *" "&PyTclObject_Type_spec"
516class _tkinter.tktimertoken "TkttObject *" "&Tktt_Type_spec"
517[clinic start generated code]*/
518/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b1ebf15c162ee229]*/
519
Guido van Rossum18468821994-06-20 07:49:28 +0000520/**** Tkapp Object ****/
521
522#ifndef WITH_APPINIT
523int
Fred Drake509d79a2000-07-08 04:04:38 +0000524Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000525{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000526 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000527
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000528 if (Tcl_Init(interp) == TCL_ERROR) {
529 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
530 return TCL_ERROR;
531 }
Guilherme Polob681df42009-02-09 22:33:59 +0000532
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 _tkinter_skip_tk_init = Tcl_GetVar(interp,
534 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
535 if (_tkinter_skip_tk_init != NULL &&
536 strcmp(_tkinter_skip_tk_init, "1") == 0) {
537 return TCL_OK;
538 }
Guilherme Polob681df42009-02-09 22:33:59 +0000539
540#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000541 if (tk_load_failed) {
542 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
543 return TCL_ERROR;
544 }
Guilherme Polob681df42009-02-09 22:33:59 +0000545#endif
546
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000548#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000549 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000550#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
552 return TCL_ERROR;
553 }
Guilherme Polob681df42009-02-09 22:33:59 +0000554
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000555 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000556}
557#endif /* !WITH_APPINIT */
558
Guido van Rossum18468821994-06-20 07:49:28 +0000559
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000560
Barry Warsawfa701a81997-01-16 00:15:11 +0000561
562/* Initialize the Tk application; see the `main' function in
563 * `tkMain.c'.
564 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000565
Thomas Wouters58d05102000-07-24 14:43:35 +0000566static void EnableEventHook(void); /* Forward */
567static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000568
Barry Warsawfa701a81997-01-16 00:15:11 +0000569static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300570Tkapp_New(const char *screenName, const char *className,
571 int interactive, int wantobjects, int wantTk, int sync,
572 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000573{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000574 TkappObject *v;
575 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000576
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300577 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000578 if (v == NULL)
579 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200580 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000581
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000582 v->interp = Tcl_CreateInterp();
583 v->wantobjects = wantobjects;
584 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
585 TCL_GLOBAL_ONLY) != NULL;
586 v->thread_id = Tcl_GetCurrentThread();
587 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000588
589#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000590 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300591 PyErr_SetString(PyExc_RuntimeError,
592 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 Py_DECREF(v);
594 return 0;
595 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000596#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000597#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 if (v->threaded && tcl_lock) {
599 /* If Tcl is threaded, we don't need the lock. */
600 PyThread_free_lock(tcl_lock);
601 tcl_lock = NULL;
602 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000603#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000604
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200605 v->OldBooleanType = Tcl_GetObjType("boolean");
606 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 v->ByteArrayType = Tcl_GetObjType("bytearray");
608 v->DoubleType = Tcl_GetObjType("double");
609 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300610 v->WideIntType = Tcl_GetObjType("wideInt");
611 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 v->ListType = Tcl_GetObjType("list");
613 v->ProcBodyType = Tcl_GetObjType("procbody");
614 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000615
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 /* Delete the 'exit' command, which can screw things up */
617 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000619 if (screenName != NULL)
620 Tcl_SetVar2(v->interp, "env", "DISPLAY",
621 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000622
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 if (interactive)
624 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
625 else
626 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000628 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200629 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 if (!argv0) {
631 PyErr_NoMemory();
632 Py_DECREF(v);
633 return NULL;
634 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000635
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200637 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
638 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200640 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000641
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000642 if (! wantTk) {
643 Tcl_SetVar(v->interp,
644 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
645 }
Guilherme Polob681df42009-02-09 22:33:59 +0000646#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 else if (tk_load_failed) {
648 Tcl_SetVar(v->interp,
649 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
650 }
Guilherme Polob681df42009-02-09 22:33:59 +0000651#endif
David Aschere2b4b322004-02-18 05:59:53 +0000652
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 /* some initial arguments need to be in argv */
654 if (sync || use) {
655 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200656 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 if (sync)
659 len += sizeof "-sync";
660 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200661 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000662
Victor Stinneree6c3c72014-09-11 17:50:21 +0200663 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 if (!args) {
665 PyErr_NoMemory();
666 Py_DECREF(v);
667 return NULL;
668 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000670 args[0] = '\0';
671 if (sync)
672 strcat(args, "-sync");
673 if (use) {
674 if (sync)
675 strcat(args, " ");
676 strcat(args, "-use ");
677 strcat(args, use);
678 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000679
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000680 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200681 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 if (Tcl_AppInit(v->interp) != TCL_OK) {
685 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000686#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 if (wantTk) {
688 const char *_tkinter_tk_failed;
689 _tkinter_tk_failed = Tcl_GetVar(v->interp,
690 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000691
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000692 if ( _tkinter_tk_failed != NULL &&
693 strcmp(_tkinter_tk_failed, "1") == 0) {
694 tk_load_failed = 1;
695 }
696 }
Guilherme Polob681df42009-02-09 22:33:59 +0000697#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000698 Py_DECREF((PyObject *)v);
699 return (TkappObject *)result;
700 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000703
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000704 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000705}
706
Barry Warsawfa701a81997-01-16 00:15:11 +0000707
Benjamin Peterson5879d412009-03-30 14:51:56 +0000708#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000709static void
710Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000711 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000712{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000713 Py_BEGIN_ALLOW_THREADS;
714 Tcl_MutexLock(mutex);
715 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
716 Tcl_ThreadAlert(self->thread_id);
717 Tcl_ConditionWait(cond, mutex, NULL);
718 Tcl_MutexUnlock(mutex);
719 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000720}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000721#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000722
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000723
Guido van Rossum18468821994-06-20 07:49:28 +0000724/** Tcl Eval **/
725
Martin v. Löwisffad6332002-11-26 09:28:05 +0000726typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000727 PyObject_HEAD
728 Tcl_Obj *value;
729 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000730} PyTclObject;
731
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300732static PyObject *PyTclObject_Type;
733#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000734
735static PyObject *
736newPyTclObject(Tcl_Obj *arg)
737{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000738 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300739 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000740 if (self == NULL)
741 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200742 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000743 Tcl_IncrRefCount(arg);
744 self->value = arg;
745 self->string = NULL;
746 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000747}
748
749static void
750PyTclObject_dealloc(PyTclObject *self)
751{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200752 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000753 Tcl_DecrRefCount(self->value);
754 Py_XDECREF(self->string);
755 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200756 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000757}
758
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000759static char*
760PyTclObject_TclString(PyObject *self)
761{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000762 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000763}
764
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000765/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000766PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000767"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000768
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000769static PyObject *
770PyTclObject_string(PyTclObject *self, void *ignored)
771{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000772 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200773 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000774 if (!self->string)
775 return NULL;
776 }
777 Py_INCREF(self->string);
778 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000779}
780
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000781static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000782PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000783{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200784 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000785 Py_INCREF(self->string);
786 return self->string;
787 }
788 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200789 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000790}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000791
Martin v. Löwisffad6332002-11-26 09:28:05 +0000792static PyObject *
793PyTclObject_repr(PyTclObject *self)
794{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300795 PyObject *repr, *str = PyTclObject_str(self, NULL);
796 if (str == NULL)
797 return NULL;
798 repr = PyUnicode_FromFormat("<%s object: %R>",
799 self->value->typePtr->name, str);
800 Py_DECREF(str);
801 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000802}
803
Mark Dickinson211c6252009-02-01 10:28:51 +0000804#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
805
806static PyObject *
807PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000808{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000809 int result;
810 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000811
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000812 /* neither argument should be NULL, unless something's gone wrong */
813 if (self == NULL || other == NULL) {
814 PyErr_BadInternalCall();
815 return NULL;
816 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000817
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000818 /* both arguments should be instances of PyTclObject */
819 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
820 v = Py_NotImplemented;
821 goto finished;
822 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000823
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000824 if (self == other)
825 /* fast path when self and other are identical */
826 result = 0;
827 else
828 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
829 Tcl_GetString(((PyTclObject *)other)->value));
830 /* Convert return value to a Boolean */
831 switch (op) {
832 case Py_EQ:
833 v = TEST_COND(result == 0);
834 break;
835 case Py_NE:
836 v = TEST_COND(result != 0);
837 break;
838 case Py_LE:
839 v = TEST_COND(result <= 0);
840 break;
841 case Py_GE:
842 v = TEST_COND(result >= 0);
843 break;
844 case Py_LT:
845 v = TEST_COND(result < 0);
846 break;
847 case Py_GT:
848 v = TEST_COND(result > 0);
849 break;
850 default:
851 PyErr_BadArgument();
852 return NULL;
853 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000854 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000855 Py_INCREF(v);
856 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000857}
858
Martin v. Löwis39195712003-01-04 00:33:13 +0000859PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
860
Martin v. Löwisffad6332002-11-26 09:28:05 +0000861static PyObject*
862get_typename(PyTclObject* obj, void* ignored)
863{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200864 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000865}
866
Martin v. Löwis39195712003-01-04 00:33:13 +0000867
Martin v. Löwisffad6332002-11-26 09:28:05 +0000868static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000869 {"typename", (getter)get_typename, NULL, get_typename__doc__},
870 {"string", (getter)PyTclObject_string, NULL,
871 PyTclObject_string__doc__},
872 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000873};
874
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300875static PyType_Slot PyTclObject_Type_slots[] = {
876 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
877 {Py_tp_repr, (reprfunc)PyTclObject_repr},
878 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200879 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300880 {Py_tp_richcompare, PyTclObject_richcompare},
881 {Py_tp_getset, PyTclObject_getsetlist},
882 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000883};
884
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300885static PyType_Spec PyTclObject_Type_spec = {
886 "_tkinter.Tcl_Obj",
887 sizeof(PyTclObject),
888 0,
889 Py_TPFLAGS_DEFAULT,
890 PyTclObject_Type_slots,
891};
892
893
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300894#if PY_SIZE_MAX > INT_MAX
895#define CHECK_STRING_LENGTH(s) do { \
896 if (s != NULL && strlen(s) >= INT_MAX) { \
897 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
898 return NULL; \
899 } } while(0)
900#else
901#define CHECK_STRING_LENGTH(s)
902#endif
903
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300904#ifdef HAVE_LIBTOMMAMTH
905static Tcl_Obj*
906asBignumObj(PyObject *value)
907{
908 Tcl_Obj *result;
909 int neg;
910 PyObject *hexstr;
911 char *hexchars;
912 mp_int bigValue;
913
914 neg = Py_SIZE(value) < 0;
915 hexstr = _PyLong_Format(value, 16);
916 if (hexstr == NULL)
917 return NULL;
918 hexchars = PyUnicode_AsUTF8(hexstr);
919 if (hexchars == NULL) {
920 Py_DECREF(hexstr);
921 return NULL;
922 }
923 hexchars += neg + 2; /* skip sign and "0x" */
924 mp_init(&bigValue);
925 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
926 mp_clear(&bigValue);
927 Py_DECREF(hexstr);
928 PyErr_NoMemory();
929 return NULL;
930 }
931 Py_DECREF(hexstr);
932 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
933 result = Tcl_NewBignumObj(&bigValue);
934 mp_clear(&bigValue);
935 if (result == NULL) {
936 PyErr_NoMemory();
937 return NULL;
938 }
939 return result;
940}
941#endif
942
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000943static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000944AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000945{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000946 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000947
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200948 if (PyBytes_Check(value)) {
949 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
950 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
951 return NULL;
952 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300953 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200954 (int)PyBytes_GET_SIZE(value));
955 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300956
957 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000958 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300959
960 if (PyLong_CheckExact(value)) {
961 int overflow;
962 long longValue;
963#ifdef TCL_WIDE_INT_TYPE
964 Tcl_WideInt wideValue;
965#endif
966 longValue = PyLong_AsLongAndOverflow(value, &overflow);
967 if (!overflow) {
968 return Tcl_NewLongObj(longValue);
969 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000970 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300971 fall through to wideInt handling. */
972#ifdef TCL_WIDE_INT_TYPE
973 if (_PyLong_AsByteArray((PyLongObject *)value,
974 (unsigned char *)(void *)&wideValue,
975 sizeof(wideValue),
976 PY_LITTLE_ENDIAN,
977 /* signed */ 1) == 0) {
978 return Tcl_NewWideIntObj(wideValue);
979 }
980 PyErr_Clear();
981#endif
982 /* If there is an overflow in the wideInt conversion,
983 fall through to bignum handling. */
984#ifdef HAVE_LIBTOMMAMTH
985 return asBignumObj(value);
986#endif
987 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000988 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000989 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300990
991 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000992 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300993
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +0300994 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300995 Tcl_Obj **argv;
996 Py_ssize_t size, i;
997
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300998 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300999 if (size == 0)
1000 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001001 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001002 PyErr_SetString(PyExc_OverflowError,
1003 PyTuple_Check(value) ? "tuple is too long" :
1004 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001005 return NULL;
1006 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001007 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
1008 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001009 PyErr_NoMemory();
1010 return NULL;
1011 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001012 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001013 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001014 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001015 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001016 return result;
1017 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001018
1019 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001020 void *inbuf;
1021 Py_ssize_t size;
1022 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001023 Tcl_UniChar *outbuf = NULL;
1024 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001025 size_t allocsize;
1026
1027 if (PyUnicode_READY(value) == -1)
1028 return NULL;
1029
1030 inbuf = PyUnicode_DATA(value);
1031 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001032 if (size == 0)
1033 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001034 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1035 PyErr_SetString(PyExc_OverflowError, "string is too long");
1036 return NULL;
1037 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001038 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001039 if (kind == sizeof(Tcl_UniChar))
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001040 return Tcl_NewUnicodeObj(inbuf, (int)size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001041 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001042 outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001043 /* Else overflow occurred, and we take the next exit */
1044 if (!outbuf) {
1045 PyErr_NoMemory();
1046 return NULL;
1047 }
1048 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001049 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1050 /* We cannot test for sizeof(Tcl_UniChar) directly,
1051 so we test for UTF-8 size instead. */
1052#if TCL_UTF_MAX == 3
1053 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001054 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001055 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001056 "character U+%x is above the range "
1057 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001058 ch);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001059 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001060 return NULL;
1061 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001062#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001063 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001064 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001065 result = Tcl_NewUnicodeObj(outbuf, (int)size);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001066 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001067 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001068 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001069
1070 if (PyTclObject_Check(value)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001071 Tcl_Obj *v = ((PyTclObject*)value)->value;
1072 Tcl_IncrRefCount(v);
1073 return v;
1074 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001075
1076 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001077 PyObject *v = PyObject_Str(value);
1078 if (!v)
1079 return 0;
1080 result = AsObj(v);
1081 Py_DECREF(v);
1082 return result;
1083 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001084}
1085
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001086static PyObject *
1087fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1088{
1089 int boolValue;
1090 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1091 return Tkinter_Error(tkapp);
1092 return PyBool_FromLong(boolValue);
1093}
1094
Martin v. Löwisffad6332002-11-26 09:28:05 +00001095static PyObject*
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001096fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1097{
1098 Tcl_WideInt wideValue;
1099 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
1100#ifdef HAVE_LONG_LONG
1101 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1102 return PyLong_FromLongLong(wideValue);
1103#endif
1104 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1105 sizeof(wideValue),
1106 PY_LITTLE_ENDIAN,
1107 /* signed */ 1);
1108 }
1109 return NULL;
1110}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001111
1112#ifdef HAVE_LIBTOMMAMTH
1113static PyObject*
1114fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1115{
1116 mp_int bigValue;
1117 unsigned long numBytes;
1118 unsigned char *bytes;
1119 PyObject *res;
1120
1121 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1122 return Tkinter_Error(tkapp);
1123 numBytes = mp_unsigned_bin_size(&bigValue);
1124 bytes = PyMem_Malloc(numBytes);
1125 if (bytes == NULL) {
1126 mp_clear(&bigValue);
1127 return PyErr_NoMemory();
1128 }
1129 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1130 &numBytes) != MP_OKAY) {
1131 mp_clear(&bigValue);
1132 PyMem_Free(bytes);
1133 return PyErr_NoMemory();
1134 }
1135 res = _PyLong_FromByteArray(bytes, numBytes,
1136 /* big-endian */ 0,
1137 /* unsigned */ 0);
1138 PyMem_Free(bytes);
1139 if (res != NULL && bigValue.sign == MP_NEG) {
1140 PyObject *res2 = PyNumber_Negative(res);
1141 Py_DECREF(res);
1142 res = res2;
1143 }
1144 mp_clear(&bigValue);
1145 return res;
1146}
1147#endif
1148
Martin v. Löwisffad6332002-11-26 09:28:05 +00001149static PyObject*
1150FromObj(PyObject* tkapp, Tcl_Obj *value)
1151{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001152 PyObject *result = NULL;
1153 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001154 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001155
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001156 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001157 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001158 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001159
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001160 if (value->typePtr == app->BooleanType ||
1161 value->typePtr == app->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001162 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001163 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001164
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001165 if (value->typePtr == app->ByteArrayType) {
1166 int size;
1167 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1168 return PyBytes_FromStringAndSize(data, size);
1169 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001170
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001171 if (value->typePtr == app->DoubleType) {
1172 return PyFloat_FromDouble(value->internalRep.doubleValue);
1173 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001174
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001175 if (value->typePtr == app->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001176 long longValue;
1177 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1178 return PyLong_FromLong(longValue);
1179 /* If there is an error in the long conversion,
1180 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001181 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001182
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001183 if (value->typePtr == app->IntType ||
1184 value->typePtr == app->WideIntType) {
1185 result = fromWideIntObj(tkapp, value);
1186 if (result != NULL || PyErr_Occurred())
1187 return result;
1188 Tcl_ResetResult(interp);
1189 /* If there is an error in the wideInt conversion,
1190 fall through to bignum handling. */
1191 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001192
1193#ifdef HAVE_LIBTOMMAMTH
1194 if (value->typePtr == app->IntType ||
1195 value->typePtr == app->WideIntType ||
1196 value->typePtr == app->BignumType) {
1197 return fromBignumObj(tkapp, value);
1198 }
1199#endif
1200
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001201 if (value->typePtr == app->ListType) {
1202 int size;
1203 int i, status;
1204 PyObject *elem;
1205 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001206
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001207 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001208 if (status == TCL_ERROR)
1209 return Tkinter_Error(tkapp);
1210 result = PyTuple_New(size);
1211 if (!result)
1212 return NULL;
1213 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001214 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001215 if (status == TCL_ERROR) {
1216 Py_DECREF(result);
1217 return Tkinter_Error(tkapp);
1218 }
1219 elem = FromObj(tkapp, tcl_elem);
1220 if (!elem) {
1221 Py_DECREF(result);
1222 return NULL;
1223 }
1224 PyTuple_SetItem(result, i, elem);
1225 }
1226 return result;
1227 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001228
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001229 if (value->typePtr == app->ProcBodyType) {
1230 /* fall through: return tcl object. */
1231 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001232
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001233 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001234 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001235 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001236 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001237 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001238
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001239#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001240 if (app->BooleanType == NULL &&
1241 strcmp(value->typePtr->name, "booleanString") == 0) {
1242 /* booleanString type is not registered in Tcl */
1243 app->BooleanType = value->typePtr;
1244 return fromBoolean(tkapp, value);
1245 }
1246#endif
1247
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001248#ifdef HAVE_LIBTOMMAMTH
1249 if (app->BignumType == NULL &&
1250 strcmp(value->typePtr->name, "bignum") == 0) {
1251 /* bignum type is not registered in Tcl */
1252 app->BignumType = value->typePtr;
1253 return fromBignumObj(tkapp, value);
1254 }
1255#endif
1256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001257 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001258}
1259
Benjamin Peterson5879d412009-03-30 14:51:56 +00001260#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001261/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001262TCL_DECLARE_MUTEX(call_mutex)
1263
1264typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001265 Tcl_Event ev; /* Must be first */
1266 TkappObject *self;
1267 PyObject *args;
1268 int flags;
1269 PyObject **res;
1270 PyObject **exc_type, **exc_value, **exc_tb;
1271 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001272} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001273#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001274
1275void
1276Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001277{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001278 int i;
1279 for (i = 0; i < objc; i++)
1280 Tcl_DecrRefCount(objv[i]);
1281 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001282 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001283}
Guido van Rossum18468821994-06-20 07:49:28 +00001284
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001285/* Convert Python objects to Tcl objects. This must happen in the
1286 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001287
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001288static Tcl_Obj**
1289Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1290{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001291 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001292 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001293 if (args == NULL)
1294 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001295
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001296 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001297 objv[0] = AsObj(args);
1298 if (objv[0] == 0)
1299 goto finally;
1300 objc = 1;
1301 Tcl_IncrRefCount(objv[0]);
1302 }
1303 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001304 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001305
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001306 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001307 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001308 PyErr_SetString(PyExc_OverflowError,
1309 PyTuple_Check(args) ? "tuple is too long" :
1310 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001311 return NULL;
1312 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001313 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001314 if (objv == NULL) {
1315 PyErr_NoMemory();
1316 objc = 0;
1317 goto finally;
1318 }
1319 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001321 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001322 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001323 if (v == Py_None) {
1324 objc = i;
1325 break;
1326 }
1327 objv[i] = AsObj(v);
1328 if (!objv[i]) {
1329 /* Reset objc, so it attempts to clear
1330 objects only up to i. */
1331 objc = i;
1332 goto finally;
1333 }
1334 Tcl_IncrRefCount(objv[i]);
1335 }
1336 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001337 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001338 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001339finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001340 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001341 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001342}
Guido van Rossum212643f1998-04-29 16:22:14 +00001343
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001344/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001345
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001346static PyObject*
1347Tkapp_CallResult(TkappObject *self)
1348{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001349 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001350 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001351 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 /* Not sure whether the IncrRef is necessary, but something
1353 may overwrite the interpreter result while we are
1354 converting it. */
1355 Tcl_IncrRefCount(value);
1356 res = FromObj((PyObject*)self, value);
1357 Tcl_DecrRefCount(value);
1358 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001359 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001360 }
1361 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001362}
Guido van Rossum632de272000-03-29 00:19:50 +00001363
Benjamin Peterson5879d412009-03-30 14:51:56 +00001364#ifdef WITH_THREAD
1365
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001366/* Tkapp_CallProc is the event procedure that is executed in the context of
1367 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1368 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001369
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001370static int
1371Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1372{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001373 Tcl_Obj *objStore[ARGSZ];
1374 Tcl_Obj **objv;
1375 int objc;
1376 int i;
1377 ENTER_PYTHON
1378 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1379 if (!objv) {
1380 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1381 *(e->res) = NULL;
1382 }
1383 LEAVE_PYTHON
1384 if (!objv)
1385 goto done;
1386 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1387 ENTER_PYTHON
1388 if (i == TCL_ERROR) {
1389 *(e->res) = NULL;
1390 *(e->exc_type) = NULL;
1391 *(e->exc_tb) = NULL;
1392 *(e->exc_value) = PyObject_CallFunction(
1393 Tkinter_TclError, "s",
1394 Tcl_GetStringResult(e->self->interp));
1395 }
1396 else {
1397 *(e->res) = Tkapp_CallResult(e->self);
1398 }
1399 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001401 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001402done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001403 /* Wake up calling thread. */
1404 Tcl_MutexLock(&call_mutex);
1405 Tcl_ConditionNotify(e->done);
1406 Tcl_MutexUnlock(&call_mutex);
1407 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001408}
1409
Benjamin Peterson5879d412009-03-30 14:51:56 +00001410#endif
1411
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001412/* This is the main entry point for calling a Tcl command.
1413 It supports three cases, with regard to threading:
1414 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1415 the context of the calling thread.
1416 2. Tcl is threaded, caller of the command is in the interpreter thread:
1417 Execute the command in the calling thread. Since the Tcl lock will
1418 not be used, we can merge that with case 1.
1419 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1420 the interpreter thread. Allocation of Tcl objects needs to occur in the
1421 interpreter thread, so we ship the PyObject* args to the target thread,
1422 and perform processing there. */
1423
1424static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001425Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001426{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001427 Tcl_Obj *objStore[ARGSZ];
1428 Tcl_Obj **objv = NULL;
1429 int objc, i;
1430 PyObject *res = NULL;
1431 TkappObject *self = (TkappObject*)selfptr;
1432 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001433
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001434 /* If args is a single tuple, replace with contents of tuple */
1435 if (1 == PyTuple_Size(args)){
1436 PyObject* item = PyTuple_GetItem(args, 0);
1437 if (PyTuple_Check(item))
1438 args = item;
1439 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001440#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001441 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1442 /* We cannot call the command directly. Instead, we must
1443 marshal the parameters to the interpreter thread. */
1444 Tkapp_CallEvent *ev;
1445 Tcl_Condition cond = NULL;
1446 PyObject *exc_type, *exc_value, *exc_tb;
1447 if (!WaitForMainloop(self))
1448 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001449 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1450 if (ev == NULL) {
1451 PyErr_NoMemory();
1452 return NULL;
1453 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001454 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1455 ev->self = self;
1456 ev->args = args;
1457 ev->res = &res;
1458 ev->exc_type = &exc_type;
1459 ev->exc_value = &exc_value;
1460 ev->exc_tb = &exc_tb;
1461 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001463 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001464
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001465 if (res == NULL) {
1466 if (exc_type)
1467 PyErr_Restore(exc_type, exc_value, exc_tb);
1468 else
1469 PyErr_SetObject(Tkinter_TclError, exc_value);
1470 }
1471 Tcl_ConditionFinalize(&cond);
1472 }
1473 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001474#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001475 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001477 objv = Tkapp_CallArgs(args, objStore, &objc);
1478 if (!objv)
1479 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001480
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001481 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001483 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001484
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001485 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001487 if (i == TCL_ERROR)
1488 Tkinter_Error(selfptr);
1489 else
1490 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001491
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001492 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001494 Tkapp_CallDeallocArgs(objv, objStore, objc);
1495 }
1496 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001497}
1498
1499
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001500/*[clinic input]
1501_tkinter.tkapp.eval
1502
1503 script: str
1504 /
1505
1506[clinic start generated code]*/
1507
Barry Warsawfa701a81997-01-16 00:15:11 +00001508static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001509_tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1510/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001511{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001512 PyObject *res = NULL;
1513 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001514
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001515 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001516 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001517
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001518 ENTER_TCL
1519 err = Tcl_Eval(Tkapp_Interp(self), script);
1520 ENTER_OVERLAP
1521 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001522 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001523 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001524 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001525 LEAVE_OVERLAP_TCL
1526 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001527}
1528
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001529/*[clinic input]
1530_tkinter.tkapp.evalfile
1531
1532 fileName: str
1533 /
1534
1535[clinic start generated code]*/
1536
Guido van Rossum18468821994-06-20 07:49:28 +00001537static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001538_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1539/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001540{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541 PyObject *res = NULL;
1542 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001543
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001544 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001545 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001546
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 ENTER_TCL
1548 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1549 ENTER_OVERLAP
1550 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001551 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001552 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001553 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001554 LEAVE_OVERLAP_TCL
1555 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001556}
1557
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001558/*[clinic input]
1559_tkinter.tkapp.record
1560
1561 script: str
1562 /
1563
1564[clinic start generated code]*/
1565
Guido van Rossum18468821994-06-20 07:49:28 +00001566static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001567_tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1568/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001569{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001570 PyObject *res = NULL;
1571 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001572
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001573 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001574 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001576 ENTER_TCL
1577 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1578 ENTER_OVERLAP
1579 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001580 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001581 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001582 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001583 LEAVE_OVERLAP_TCL
1584 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001585}
1586
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001587/*[clinic input]
1588_tkinter.tkapp.adderrinfo
Guido van Rossum18468821994-06-20 07:49:28 +00001589
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001590 msg: str
1591 /
1592
1593[clinic start generated code]*/
1594
1595static PyObject *
1596_tkinter_tkapp_adderrinfo_impl(TkappObject *self, const char *msg)
1597/*[clinic end generated code: output=0e222ee2050eb357 input=4971399317d4c136]*/
1598{
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001599 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001600 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001602 ENTER_TCL
1603 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1604 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001605
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001606 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001607}
1608
Barry Warsawfa701a81997-01-16 00:15:11 +00001609
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001610
Guido van Rossum18468821994-06-20 07:49:28 +00001611/** Tcl Variable **/
1612
Benjamin Peterson5879d412009-03-30 14:51:56 +00001613typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1614
1615#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001616TCL_DECLARE_MUTEX(var_mutex)
1617
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001618typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001619 Tcl_Event ev; /* must be first */
1620 PyObject *self;
1621 PyObject *args;
1622 int flags;
1623 EventFunc func;
1624 PyObject **res;
1625 PyObject **exc_type;
1626 PyObject **exc_val;
1627 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001628} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001629#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001630
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001631/*[python]
1632
1633class varname_converter(CConverter):
1634 type = 'const char *'
1635 converter = 'varname_converter'
1636
1637[python]*/
1638/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1639
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001640static int
1641varname_converter(PyObject *in, void *_out)
1642{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001643 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001644 char **out = (char**)_out;
1645 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001646 if (PyBytes_Size(in) > INT_MAX) {
1647 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1648 return 0;
1649 }
1650 s = PyBytes_AsString(in);
Victor Stinner706768c2014-08-16 01:03:39 +02001651 if (strlen(s) != (size_t)PyBytes_Size(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001652 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001653 return 0;
1654 }
1655 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001656 return 1;
1657 }
1658 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001659 Py_ssize_t size;
1660 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001661 if (s == NULL) {
1662 return 0;
1663 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001664 if (size > INT_MAX) {
1665 PyErr_SetString(PyExc_OverflowError, "string is too long");
1666 return 0;
1667 }
Victor Stinner706768c2014-08-16 01:03:39 +02001668 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001669 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001670 return 0;
1671 }
1672 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001673 return 1;
1674 }
1675 if (PyTclObject_Check(in)) {
1676 *out = PyTclObject_TclString(in);
1677 return 1;
1678 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001679 PyErr_Format(PyExc_TypeError,
1680 "must be str, bytes or Tcl_Obj, not %.50s",
1681 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001682 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001683}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001684
Benjamin Peterson5879d412009-03-30 14:51:56 +00001685#ifdef WITH_THREAD
1686
Martin v. Löwis59683e82008-06-13 07:50:45 +00001687static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001688var_perform(VarEvent *ev)
1689{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001690 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1691 if (!*(ev->res)) {
1692 PyObject *exc, *val, *tb;
1693 PyErr_Fetch(&exc, &val, &tb);
1694 PyErr_NormalizeException(&exc, &val, &tb);
1695 *(ev->exc_type) = exc;
1696 *(ev->exc_val) = val;
1697 Py_DECREF(tb);
1698 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001699
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001700}
1701
1702static int
1703var_proc(VarEvent* ev, int flags)
1704{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001705 ENTER_PYTHON
1706 var_perform(ev);
1707 Tcl_MutexLock(&var_mutex);
1708 Tcl_ConditionNotify(ev->cond);
1709 Tcl_MutexUnlock(&var_mutex);
1710 LEAVE_PYTHON
1711 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001712}
1713
Benjamin Peterson5879d412009-03-30 14:51:56 +00001714#endif
1715
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001716static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001717var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001718{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001719#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001720 TkappObject *self = (TkappObject*)selfptr;
1721 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001722 VarEvent *ev;
1723 PyObject *res, *exc_type, *exc_val;
1724 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001725
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001726 /* The current thread is not the interpreter thread. Marshal
1727 the call to the interpreter thread, then wait for
1728 completion. */
1729 if (!WaitForMainloop(self))
1730 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001731
Serhiy Storchaka07940882014-09-11 10:38:54 +03001732 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1733 if (ev == NULL) {
1734 PyErr_NoMemory();
1735 return NULL;
1736 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001737 ev->self = selfptr;
1738 ev->args = args;
1739 ev->flags = flags;
1740 ev->func = func;
1741 ev->res = &res;
1742 ev->exc_type = &exc_type;
1743 ev->exc_val = &exc_val;
1744 ev->cond = &cond;
1745 ev->ev.proc = (Tcl_EventProc*)var_proc;
1746 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1747 Tcl_ConditionFinalize(&cond);
1748 if (!res) {
1749 PyErr_SetObject(exc_type, exc_val);
1750 Py_DECREF(exc_type);
1751 Py_DECREF(exc_val);
1752 return NULL;
1753 }
1754 return res;
1755 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001756#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001757 /* Tcl is not threaded, or this is the interpreter thread. */
1758 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001759}
1760
Guido van Rossum18468821994-06-20 07:49:28 +00001761static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001762SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001763{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001764 char *name1, *name2;
1765 PyObject *newValue;
1766 PyObject *res = NULL;
1767 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001768
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001769 switch (PyTuple_GET_SIZE(args)) {
1770 case 2:
1771 if (!PyArg_ParseTuple(args, "O&O:setvar",
1772 varname_converter, &name1, &newValue))
1773 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001774 /* XXX Acquire tcl lock??? */
1775 newval = AsObj(newValue);
1776 if (newval == NULL)
1777 return NULL;
1778 ENTER_TCL
1779 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1780 newval, flags);
1781 ENTER_OVERLAP
1782 if (!ok)
1783 Tkinter_Error(self);
1784 else {
1785 res = Py_None;
1786 Py_INCREF(res);
1787 }
1788 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001789 break;
1790 case 3:
1791 if (!PyArg_ParseTuple(args, "ssO:setvar",
1792 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001793 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001794 CHECK_STRING_LENGTH(name1);
1795 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001796 /* XXX must hold tcl lock already??? */
1797 newval = AsObj(newValue);
1798 ENTER_TCL
1799 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1800 ENTER_OVERLAP
1801 if (!ok)
1802 Tkinter_Error(self);
1803 else {
1804 res = Py_None;
1805 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001806 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001807 LEAVE_OVERLAP_TCL
1808 break;
1809 default:
1810 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1811 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001812 }
1813 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001814}
1815
1816static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001817Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001818{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001819 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001820}
1821
1822static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001823Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001824{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001825 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001826}
1827
Barry Warsawfa701a81997-01-16 00:15:11 +00001828
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001829
Guido van Rossum18468821994-06-20 07:49:28 +00001830static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001831GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001832{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001833 char *name1, *name2=NULL;
1834 PyObject *res = NULL;
1835 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001837 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1838 varname_converter, &name1, &name2))
1839 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001840
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001841 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001842 ENTER_TCL
1843 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1844 ENTER_OVERLAP
1845 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001846 PyErr_SetString(Tkinter_TclError,
1847 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001848 } else {
1849 if (((TkappObject*)self)->wantobjects) {
1850 res = FromObj(self, tres);
1851 }
1852 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001853 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001854 }
1855 }
1856 LEAVE_OVERLAP_TCL
1857 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001858}
1859
1860static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001861Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001862{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001863 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001864}
1865
1866static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001867Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001868{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001869 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001870}
1871
Barry Warsawfa701a81997-01-16 00:15:11 +00001872
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001873
Guido van Rossum18468821994-06-20 07:49:28 +00001874static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001875UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001876{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001877 char *name1, *name2=NULL;
1878 int code;
1879 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001880
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001881 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1882 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001883
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001884 CHECK_STRING_LENGTH(name1);
1885 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001886 ENTER_TCL
1887 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1888 ENTER_OVERLAP
1889 if (code == TCL_ERROR)
1890 res = Tkinter_Error(self);
1891 else {
1892 Py_INCREF(Py_None);
1893 res = Py_None;
1894 }
1895 LEAVE_OVERLAP_TCL
1896 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001897}
1898
1899static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001900Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001901{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001902 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001903}
1904
1905static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001906Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001907{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001908 return var_invoke(UnsetVar, self, args,
1909 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001910}
1911
Barry Warsawfa701a81997-01-16 00:15:11 +00001912
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001913
Guido van Rossum18468821994-06-20 07:49:28 +00001914/** Tcl to Python **/
1915
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001916/*[clinic input]
1917_tkinter.tkapp.getint
1918
1919 arg: object
1920 /
1921
1922[clinic start generated code]*/
1923
Guido van Rossum18468821994-06-20 07:49:28 +00001924static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001925_tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
1926/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001927{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001928 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001929 Tcl_Obj *value;
1930 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00001931
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001932 if (PyLong_Check(arg)) {
1933 Py_INCREF(arg);
1934 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001935 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001936
1937 if (!PyArg_Parse(arg, "s:getint", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001938 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001939 CHECK_STRING_LENGTH(s);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001940 value = Tcl_NewStringObj(s, -1);
1941 if (value == NULL)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001942 return Tkinter_Error((PyObject *)self);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001943 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
1944 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
1945
1946 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
1947 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
1948 */
1949#ifdef HAVE_LIBTOMMAMTH
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001950 result = fromBignumObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001951#else
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001952 result = fromWideIntObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001953#endif
1954 Tcl_DecrRefCount(value);
1955 if (result != NULL || PyErr_Occurred())
1956 return result;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001957 return Tkinter_Error((PyObject *)self);
Guido van Rossum18468821994-06-20 07:49:28 +00001958}
1959
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001960/*[clinic input]
1961_tkinter.tkapp.getdouble
1962
1963 arg: object
1964 /
1965
1966[clinic start generated code]*/
1967
Guido van Rossum18468821994-06-20 07:49:28 +00001968static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001969_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
1970/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001971{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001972 char *s;
1973 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001974
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001975 if (PyFloat_Check(arg)) {
1976 Py_INCREF(arg);
1977 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001978 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001979
1980 if (!PyArg_Parse(arg, "s:getdouble", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001981 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001982 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001983 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001984 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001985 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001986}
1987
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001988/*[clinic input]
1989_tkinter.tkapp.getboolean
1990
1991 arg: object
1992 /
1993
1994[clinic start generated code]*/
1995
Guido van Rossum18468821994-06-20 07:49:28 +00001996static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001997_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
1998/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001999{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002000 char *s;
2001 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002002
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002003 if (PyLong_Check(arg)) { /* int or bool */
2004 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002005 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002006
2007 if (PyTclObject_Check(arg)) {
2008 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2009 ((PyTclObject*)arg)->value,
2010 &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002011 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002012 return PyBool_FromLong(v);
2013 }
2014
2015 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002016 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002017 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002018 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002019 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002020 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002021}
2022
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002023/*[clinic input]
2024_tkinter.tkapp.exprstring
2025
2026 s: str
2027 /
2028
2029[clinic start generated code]*/
2030
Guido van Rossum18468821994-06-20 07:49:28 +00002031static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002032_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2033/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002034{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002035 PyObject *res = NULL;
2036 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002037
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002038 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002039 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002040
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002041 ENTER_TCL
2042 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2043 ENTER_OVERLAP
2044 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002045 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002046 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002047 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002048 LEAVE_OVERLAP_TCL
2049 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002050}
2051
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002052/*[clinic input]
2053_tkinter.tkapp.exprlong
2054
2055 s: str
2056 /
2057
2058[clinic start generated code]*/
2059
Guido van Rossum18468821994-06-20 07:49:28 +00002060static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002061_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2062/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002063{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002064 PyObject *res = NULL;
2065 int retval;
2066 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002067
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002068 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002069 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002071 ENTER_TCL
2072 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2073 ENTER_OVERLAP
2074 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002075 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002076 else
2077 res = Py_BuildValue("l", v);
2078 LEAVE_OVERLAP_TCL
2079 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002080}
2081
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002082/*[clinic input]
2083_tkinter.tkapp.exprdouble
2084
2085 s: str
2086 /
2087
2088[clinic start generated code]*/
2089
Guido van Rossum18468821994-06-20 07:49:28 +00002090static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002091_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2092/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002093{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002094 PyObject *res = NULL;
2095 double v;
2096 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002097
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002098 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002099 CHECK_TCL_APPARTMENT;
2100 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2101 ENTER_TCL
2102 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2103 ENTER_OVERLAP
2104 PyFPE_END_PROTECT(retval)
2105 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002106 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002107 else
2108 res = Py_BuildValue("d", v);
2109 LEAVE_OVERLAP_TCL
2110 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002111}
2112
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002113/*[clinic input]
2114_tkinter.tkapp.exprboolean
2115
2116 s: str
2117 /
2118
2119[clinic start generated code]*/
2120
Guido van Rossum18468821994-06-20 07:49:28 +00002121static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002122_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2123/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002124{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002125 PyObject *res = NULL;
2126 int retval;
2127 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002128
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002129 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002130 CHECK_TCL_APPARTMENT;
2131 ENTER_TCL
2132 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2133 ENTER_OVERLAP
2134 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002135 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002136 else
2137 res = Py_BuildValue("i", v);
2138 LEAVE_OVERLAP_TCL
2139 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002140}
2141
Barry Warsawfa701a81997-01-16 00:15:11 +00002142
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002143
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002144/*[clinic input]
2145_tkinter.tkapp.splitlist
2146
2147 arg: object
2148 /
2149
2150[clinic start generated code]*/
2151
Guido van Rossum18468821994-06-20 07:49:28 +00002152static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002153_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2154/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002155{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002156 char *list;
2157 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002158 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002159 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002161
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002162 if (PyTclObject_Check(arg)) {
2163 int objc;
2164 Tcl_Obj **objv;
2165 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2166 ((PyTclObject*)arg)->value,
2167 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002168 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002169 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002170 if (!(v = PyTuple_New(objc)))
2171 return NULL;
2172 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002173 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002174 if (!s || PyTuple_SetItem(v, i, s)) {
2175 Py_DECREF(v);
2176 return NULL;
2177 }
2178 }
2179 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002180 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002181 if (PyTuple_Check(arg)) {
2182 Py_INCREF(arg);
2183 return arg;
2184 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002185 if (PyList_Check(arg)) {
2186 return PySequence_Tuple(arg);
2187 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002188
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002189 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002190 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002191
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002192 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002193 if (Tcl_SplitList(Tkapp_Interp(self), list,
2194 &argc, &argv) == TCL_ERROR) {
2195 PyMem_Free(list);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002196 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 }
Guido van Rossum18468821994-06-20 07:49:28 +00002198
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002199 if (!(v = PyTuple_New(argc)))
2200 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002201
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002202 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002203 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002204 if (!s || PyTuple_SetItem(v, i, s)) {
2205 Py_DECREF(v);
2206 v = NULL;
2207 goto finally;
2208 }
2209 }
Guido van Rossum18468821994-06-20 07:49:28 +00002210
Barry Warsawfa701a81997-01-16 00:15:11 +00002211 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002212 ckfree(FREECAST argv);
2213 PyMem_Free(list);
2214 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002215}
2216
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002217/*[clinic input]
2218_tkinter.tkapp.split
2219
2220 arg: object
2221 /
2222
2223[clinic start generated code]*/
2224
Guido van Rossum18468821994-06-20 07:49:28 +00002225static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002226_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2227/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002228{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002229 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002230 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002231
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002232 if (PyTclObject_Check(arg)) {
2233 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2234 int objc;
2235 Tcl_Obj **objv;
2236 int i;
2237 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2238 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002239 return FromObj((PyObject*)self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002240 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002241 if (objc == 0)
2242 return PyUnicode_FromString("");
2243 if (objc == 1)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002244 return FromObj((PyObject*)self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002245 if (!(v = PyTuple_New(objc)))
2246 return NULL;
2247 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002248 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002249 if (!s || PyTuple_SetItem(v, i, s)) {
2250 Py_DECREF(v);
2251 return NULL;
2252 }
2253 }
2254 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002255 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002256 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002257 return SplitObj(arg);
2258
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002259 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002260 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002261 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002262 v = Split(list);
2263 PyMem_Free(list);
2264 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002265}
2266
Barry Warsawfa701a81997-01-16 00:15:11 +00002267
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002268
Guido van Rossum18468821994-06-20 07:49:28 +00002269/** Tcl Command **/
2270
Guido van Rossum00d93061998-05-28 23:06:38 +00002271/* Client data struct */
2272typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002273 PyObject *self;
2274 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002275} PythonCmd_ClientData;
2276
2277static int
Fred Drake509d79a2000-07-08 04:04:38 +00002278PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002279{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002280 errorInCmd = 1;
2281 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2282 LEAVE_PYTHON
2283 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002284}
2285
Guido van Rossum18468821994-06-20 07:49:28 +00002286/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002287 * function or method.
2288 */
Guido van Rossum18468821994-06-20 07:49:28 +00002289static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002290PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002291{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002292 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002293 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002294 int i, rv;
2295 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002297 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299 /* TBD: no error checking here since we know, via the
2300 * Tkapp_CreateCommand() that the client data is a two-tuple
2301 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002302 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002303
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002304 /* Create argument list (argv1, ..., argvN) */
2305 if (!(arg = PyTuple_New(argc - 1)))
2306 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002307
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002308 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002309 PyObject *s = unicodeFromTclString(argv[i + 1]);
2310 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002311 Py_DECREF(arg);
2312 return PythonCmd_Error(interp);
2313 }
2314 }
2315 res = PyEval_CallObject(func, arg);
2316 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002317
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002318 if (res == NULL)
2319 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002321 obj_res = AsObj(res);
2322 if (obj_res == NULL) {
2323 Py_DECREF(res);
2324 return PythonCmd_Error(interp);
2325 }
2326 else {
2327 Tcl_SetObjResult(interp, obj_res);
2328 rv = TCL_OK;
2329 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002330
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002331 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002332
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002333 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002334
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002335 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002336}
2337
2338static void
Fred Drake509d79a2000-07-08 04:04:38 +00002339PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002340{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002341 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002343 ENTER_PYTHON
2344 Py_XDECREF(data->self);
2345 Py_XDECREF(data->func);
2346 PyMem_DEL(data);
2347 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002348}
2349
Barry Warsawfa701a81997-01-16 00:15:11 +00002350
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002351
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002352
Benjamin Peterson5879d412009-03-30 14:51:56 +00002353#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002354TCL_DECLARE_MUTEX(command_mutex)
2355
2356typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002357 Tcl_Event ev;
2358 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002359 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002360 int create;
2361 int *status;
2362 ClientData *data;
2363 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002364} CommandEvent;
2365
2366static int
2367Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002368{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002369 if (ev->create)
2370 *ev->status = Tcl_CreateCommand(
2371 ev->interp, ev->name, PythonCmd,
2372 ev->data, PythonCmdDelete) == NULL;
2373 else
2374 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2375 Tcl_MutexLock(&command_mutex);
2376 Tcl_ConditionNotify(ev->done);
2377 Tcl_MutexUnlock(&command_mutex);
2378 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002379}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002380#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002381
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002382/*[clinic input]
2383_tkinter.tkapp.createcommand
2384
2385 self: self(type="TkappObject *")
2386 name: str
2387 func: object
2388 /
2389
2390[clinic start generated code]*/
2391
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002392static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002393_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2394 PyObject *func)
2395/*[clinic end generated code: output=2a1c79a4ee2af410 input=2bc2c046a0914234]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002396{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002397 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002398 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002399
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002400 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002401 if (!PyCallable_Check(func)) {
2402 PyErr_SetString(PyExc_TypeError, "command not callable");
2403 return NULL;
2404 }
Guido van Rossum18468821994-06-20 07:49:28 +00002405
Martin v. Löwisa9656492003-03-30 08:44:58 +00002406#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2408 !WaitForMainloop(self))
2409 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002410#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002411
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002412 data = PyMem_NEW(PythonCmd_ClientData, 1);
2413 if (!data)
2414 return PyErr_NoMemory();
2415 Py_INCREF(self);
2416 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002417 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002418 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002419#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002420 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2421 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002422 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2423 if (ev == NULL) {
2424 PyErr_NoMemory();
2425 PyMem_DEL(data);
2426 return NULL;
2427 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002428 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2429 ev->interp = self->interp;
2430 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002431 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002432 ev->data = (ClientData)data;
2433 ev->status = &err;
2434 ev->done = &cond;
2435 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2436 Tcl_ConditionFinalize(&cond);
2437 }
2438 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002439#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002440 {
2441 ENTER_TCL
2442 err = Tcl_CreateCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002443 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002444 (ClientData)data, PythonCmdDelete) == NULL;
2445 LEAVE_TCL
2446 }
2447 if (err) {
2448 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2449 PyMem_DEL(data);
2450 return NULL;
2451 }
Guido van Rossum18468821994-06-20 07:49:28 +00002452
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002453 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002454}
2455
Barry Warsawfa701a81997-01-16 00:15:11 +00002456
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002457
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002458/*[clinic input]
2459_tkinter.tkapp.deletecommand
2460
2461 self: self(type="TkappObject *")
2462 name: str
2463 /
2464
2465[clinic start generated code]*/
2466
Guido van Rossum18468821994-06-20 07:49:28 +00002467static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002468_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
2469/*[clinic end generated code: output=a67e8cb5845e0d2d input=b6306468f10b219c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002470{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002472
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002473 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002474
2475#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002476 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2477 Tcl_Condition cond = NULL;
2478 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002479 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2480 if (ev == NULL) {
2481 PyErr_NoMemory();
2482 return NULL;
2483 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002484 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2485 ev->interp = self->interp;
2486 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002487 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002488 ev->status = &err;
2489 ev->done = &cond;
2490 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2491 &command_mutex);
2492 Tcl_ConditionFinalize(&cond);
2493 }
2494 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002495#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002496 {
2497 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002498 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002499 LEAVE_TCL
2500 }
2501 if (err == -1) {
2502 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2503 return NULL;
2504 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002505 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002506}
2507
Barry Warsawfa701a81997-01-16 00:15:11 +00002508
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002509
Guido van Rossum00d93061998-05-28 23:06:38 +00002510#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002511/** File Handler **/
2512
Guido van Rossum00d93061998-05-28 23:06:38 +00002513typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002514 PyObject *func;
2515 PyObject *file;
2516 int id;
2517 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002518} FileHandler_ClientData;
2519
2520static FileHandler_ClientData *HeadFHCD;
2521
2522static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002523NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002524{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002525 FileHandler_ClientData *p;
2526 p = PyMem_NEW(FileHandler_ClientData, 1);
2527 if (p != NULL) {
2528 Py_XINCREF(func);
2529 Py_XINCREF(file);
2530 p->func = func;
2531 p->file = file;
2532 p->id = id;
2533 p->next = HeadFHCD;
2534 HeadFHCD = p;
2535 }
2536 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002537}
2538
2539static void
Fred Drake509d79a2000-07-08 04:04:38 +00002540DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002541{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002542 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002543
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002544 pp = &HeadFHCD;
2545 while ((p = *pp) != NULL) {
2546 if (p->id == id) {
2547 *pp = p->next;
2548 Py_XDECREF(p->func);
2549 Py_XDECREF(p->file);
2550 PyMem_DEL(p);
2551 }
2552 else
2553 pp = &p->next;
2554 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002555}
2556
Guido van Rossuma597dde1995-01-10 20:56:29 +00002557static void
Fred Drake509d79a2000-07-08 04:04:38 +00002558FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002559{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2561 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002562
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002563 ENTER_PYTHON
2564 func = data->func;
2565 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002567 arg = Py_BuildValue("(Oi)", file, (long) mask);
2568 res = PyEval_CallObject(func, arg);
2569 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002571 if (res == NULL) {
2572 errorInCmd = 1;
2573 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2574 }
2575 Py_XDECREF(res);
2576 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002577}
2578
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002579/*[clinic input]
2580_tkinter.tkapp.createfilehandler
2581
2582 file: object
2583 mask: int
2584 func: object
2585 /
2586
2587[clinic start generated code]*/
2588
Guido van Rossum18468821994-06-20 07:49:28 +00002589static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002590_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2591 int mask, PyObject *func)
2592/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002593{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002594 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002595 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002596
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002597 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002598
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002599 tfile = PyObject_AsFileDescriptor(file);
2600 if (tfile < 0)
2601 return NULL;
2602 if (!PyCallable_Check(func)) {
2603 PyErr_SetString(PyExc_TypeError, "bad argument list");
2604 return NULL;
2605 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002607 data = NewFHCD(func, file, tfile);
2608 if (data == NULL)
2609 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002611 /* Ought to check for null Tcl_File object... */
2612 ENTER_TCL
2613 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2614 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002615 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002616}
2617
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002618/*[clinic input]
2619_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002620
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002621 file: object
2622 /
2623
2624[clinic start generated code]*/
2625
2626static PyObject *
2627_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2628/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2629{
2630 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002632 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002634 tfile = PyObject_AsFileDescriptor(file);
2635 if (tfile < 0)
2636 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002637
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002638 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002639
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002640 /* Ought to check for null Tcl_File object... */
2641 ENTER_TCL
2642 Tcl_DeleteFileHandler(tfile);
2643 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002644 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002645}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002646#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002648
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002649/**** Tktt Object (timer token) ****/
2650
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002651static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002652
Guido van Rossum00d93061998-05-28 23:06:38 +00002653typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002654 PyObject_HEAD
2655 Tcl_TimerToken token;
2656 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002657} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002658
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002659/*[clinic input]
2660_tkinter.tktimertoken.deletetimerhandler
2661
2662 self: self(type="TkttObject *")
2663
2664[clinic start generated code]*/
2665
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002666static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002667_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
2668/*[clinic end generated code: output=bd7fe17f328cfa55 input=25ba5dd594e52084]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002669{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002670 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002671 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002673 if (v->token != NULL) {
2674 Tcl_DeleteTimerHandler(v->token);
2675 v->token = NULL;
2676 }
2677 if (func != NULL) {
2678 v->func = NULL;
2679 Py_DECREF(func);
2680 Py_DECREF(v); /* See Tktt_New() */
2681 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002682 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002683}
2684
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002685static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002686Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002687{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002688 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002689
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002690 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002691 if (v == NULL)
2692 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002693 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002695 Py_INCREF(func);
2696 v->token = NULL;
2697 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002698
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002699 /* Extra reference, deleted when called or when handler is deleted */
2700 Py_INCREF(v);
2701 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002702}
2703
2704static void
Fred Drake509d79a2000-07-08 04:04:38 +00002705Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002706{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002707 TkttObject *v = (TkttObject *)self;
2708 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002709 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002710
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002711 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002712
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002713 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002714 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002715}
2716
Guido van Rossum597ac201998-05-12 14:36:19 +00002717static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002718Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002719{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002720 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002721 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2722 v,
2723 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002724}
2725
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002726/** Timer Handler **/
2727
2728static void
Fred Drake509d79a2000-07-08 04:04:38 +00002729TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002730{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002731 TkttObject *v = (TkttObject *)clientData;
2732 PyObject *func = v->func;
2733 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002734
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002735 if (func == NULL)
2736 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002737
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002738 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002739
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002740 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002741
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002742 res = PyEval_CallObject(func, NULL);
2743 Py_DECREF(func);
2744 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002745
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002746 if (res == NULL) {
2747 errorInCmd = 1;
2748 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2749 }
2750 else
2751 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002752
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002753 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002754}
2755
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002756/*[clinic input]
2757_tkinter.tkapp.createtimerhandler
2758
2759 milliseconds: int
2760 func: object
2761 /
2762
2763[clinic start generated code]*/
2764
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002765static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002766_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2767 PyObject *func)
2768/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002769{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002770 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002771
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002772 if (!PyCallable_Check(func)) {
2773 PyErr_SetString(PyExc_TypeError, "bad argument list");
2774 return NULL;
2775 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002776
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002777 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002778
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002779 v = Tktt_New(func);
2780 if (v) {
2781 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2782 (ClientData)v);
2783 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002784
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002785 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002786}
2787
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002788
Guido van Rossum18468821994-06-20 07:49:28 +00002789/** Event Loop **/
2790
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002791/*[clinic input]
2792_tkinter.tkapp.mainloop
2793
2794 self: self(type="TkappObject *")
2795 threshold: int = 0
2796 /
2797
2798[clinic start generated code]*/
2799
Guido van Rossum18468821994-06-20 07:49:28 +00002800static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002801_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
2802/*[clinic end generated code: output=0ba8eabbe57841b0 input=ad57c9c1dd2b9470]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002803{
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002804#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002805 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002806#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002807
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002808 CHECK_TCL_APPARTMENT;
2809 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002810
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002811 quitMainLoop = 0;
2812 while (Tk_GetNumMainWindows() > threshold &&
2813 !quitMainLoop &&
2814 !errorInCmd)
2815 {
2816 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002817
2818#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002819 if (self->threaded) {
2820 /* Allow other Python threads to run. */
2821 ENTER_TCL
2822 result = Tcl_DoOneEvent(0);
2823 LEAVE_TCL
2824 }
2825 else {
2826 Py_BEGIN_ALLOW_THREADS
2827 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2828 tcl_tstate = tstate;
2829 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2830 tcl_tstate = NULL;
2831 if(tcl_lock)PyThread_release_lock(tcl_lock);
2832 if (result == 0)
2833 Sleep(Tkinter_busywaitinterval);
2834 Py_END_ALLOW_THREADS
2835 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002836#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002837 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002838#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002839
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002840 if (PyErr_CheckSignals() != 0) {
2841 self->dispatching = 0;
2842 return NULL;
2843 }
2844 if (result < 0)
2845 break;
2846 }
2847 self->dispatching = 0;
2848 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002849
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002850 if (errorInCmd) {
2851 errorInCmd = 0;
2852 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2853 excInCmd = valInCmd = trbInCmd = NULL;
2854 return NULL;
2855 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002856 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002857}
2858
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002859/*[clinic input]
2860_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002861
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002862 flags: int = 0
2863 /
2864
2865[clinic start generated code]*/
2866
2867static PyObject *
2868_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2869/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2870{
2871 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002872
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002873 ENTER_TCL
2874 rv = Tcl_DoOneEvent(flags);
2875 LEAVE_TCL
2876 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002877}
2878
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002879/*[clinic input]
2880_tkinter.tkapp.quit
2881[clinic start generated code]*/
2882
Guido van Rossum062cfb01995-01-10 17:42:51 +00002883static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002884_tkinter_tkapp_quit_impl(TkappObject *self)
2885/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002886{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002887 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002888 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002889}
2890
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002891/*[clinic input]
2892_tkinter.tkapp.interpaddr
2893[clinic start generated code]*/
2894
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002895static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002896_tkinter_tkapp_interpaddr_impl(TkappObject *self)
2897/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002898{
Victor Stinnere1040e22013-09-05 00:22:24 +02002899 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002900}
2901
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002902/*[clinic input]
2903_tkinter.tkapp.loadtk
2904[clinic start generated code]*/
2905
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002906static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002907_tkinter_tkapp_loadtk_impl(TkappObject *self)
2908/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00002909{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002910 Tcl_Interp *interp = Tkapp_Interp(self);
2911 const char * _tk_exists = NULL;
2912 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002913
Guilherme Polob681df42009-02-09 22:33:59 +00002914#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002915 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2916 * first call failed.
2917 * To avoid the deadlock, we just refuse the second call through
2918 * a static variable.
2919 */
2920 if (tk_load_failed) {
2921 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2922 return NULL;
2923 }
Guilherme Polob681df42009-02-09 22:33:59 +00002924#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002925
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002926 /* We want to guard against calling Tk_Init() multiple times */
2927 CHECK_TCL_APPARTMENT;
2928 ENTER_TCL
2929 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2930 ENTER_OVERLAP
2931 if (err == TCL_ERROR) {
2932 /* This sets an exception, but we cannot return right
2933 away because we need to exit the overlap first. */
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002934 Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002935 } else {
2936 _tk_exists = Tkapp_Result(self);
2937 }
2938 LEAVE_OVERLAP_TCL
2939 if (err == TCL_ERROR) {
2940 return NULL;
2941 }
2942 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2943 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002944 PyErr_SetString(Tkinter_TclError,
2945 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002946#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002947 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002948#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002949 return NULL;
2950 }
2951 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002952 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002953}
Barry Warsawfa701a81997-01-16 00:15:11 +00002954
Martin v. Löwisffad6332002-11-26 09:28:05 +00002955static PyObject *
2956Tkapp_WantObjects(PyObject *self, PyObject *args)
2957{
2958
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002959 int wantobjects = -1;
2960 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2961 return NULL;
2962 if (wantobjects == -1)
2963 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2964 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002965
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002966 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002967}
2968
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002969/*[clinic input]
2970_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002971
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002972 self: self(type="TkappObject *")
2973
2974[clinic start generated code]*/
2975
2976static PyObject *
2977_tkinter_tkapp_willdispatch_impl(TkappObject *self)
2978/*[clinic end generated code: output=0e3f46d244642155 input=2630699767808970]*/
2979{
2980 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002981
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002982 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002983}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002984
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002985
Guido van Rossum18468821994-06-20 07:49:28 +00002986/**** Tkapp Type Methods ****/
2987
2988static void
Fred Drake509d79a2000-07-08 04:04:38 +00002989Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002990{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002991 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002992 /*CHECK_TCL_APPARTMENT;*/
2993 ENTER_TCL
2994 Tcl_DeleteInterp(Tkapp_Interp(self));
2995 LEAVE_TCL
2996 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002997 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002998 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002999}
3000
Barry Warsawfa701a81997-01-16 00:15:11 +00003001
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003002
Guido van Rossum18468821994-06-20 07:49:28 +00003003/**** Tkinter Module ****/
3004
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003005typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003006 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003007 Py_ssize_t size; /* current size */
3008 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003009} FlattenContext;
3010
3011static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003012_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003013{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003014 /* expand tuple to hold (at least) size new items.
3015 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003016
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003017 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003018
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003019 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003020 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003021
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003022 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003023
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003024 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003025}
3026
3027static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003028_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003029{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003030 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003031
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003032 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003033
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003034 if (depth > 1000) {
3035 PyErr_SetString(PyExc_ValueError,
3036 "nesting too deep in _flatten");
3037 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003038 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3039 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003040 /* preallocate (assume no nesting) */
3041 if (context->size + size > context->maxsize &&
3042 !_bump(context, size))
3043 return 0;
3044 /* copy items to output tuple */
3045 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003046 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003047 if (PyList_Check(o) || PyTuple_Check(o)) {
3048 if (!_flatten1(context, o, depth + 1))
3049 return 0;
3050 } else if (o != Py_None) {
3051 if (context->size + 1 > context->maxsize &&
3052 !_bump(context, 1))
3053 return 0;
3054 Py_INCREF(o);
3055 PyTuple_SET_ITEM(context->tuple,
3056 context->size++, o);
3057 }
3058 }
3059 } else {
3060 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3061 return 0;
3062 }
3063 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003064}
3065
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003066/*[clinic input]
3067_tkinter._flatten
3068
3069 item: object
3070 /
3071
3072[clinic start generated code]*/
3073
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003074static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003075_tkinter__flatten(PyModuleDef *module, PyObject *item)
3076/*[clinic end generated code: output=9505049ec74c3480 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003077{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003078 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003079
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003080 context.maxsize = PySequence_Size(item);
3081 if (context.maxsize < 0)
3082 return NULL;
3083 if (context.maxsize == 0)
3084 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003085
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003086 context.tuple = PyTuple_New(context.maxsize);
3087 if (!context.tuple)
3088 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003089
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003090 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003091
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003092 if (!_flatten1(&context, item,0))
3093 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003094
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003095 if (_PyTuple_Resize(&context.tuple, context.size))
3096 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003097
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003098 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003099}
3100
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003101/*[clinic input]
3102_tkinter.create
3103
3104 screenName: str(nullable=True) = NULL
3105 baseName: str = NULL
3106 className: str = "Tk"
3107 interactive: int(c_default="0") = False
3108 wantobjects: int(c_default="0") = False
3109 wantTk: int(c_default="1") = True
3110 if false, then Tk_Init() doesn't get called
3111 sync: int(c_default="0") = False
3112 if true, then pass -sync to wish
3113 use: str(nullable=True) = NULL
3114 if not None, then pass -use to wish
3115 /
3116
3117[clinic start generated code]*/
3118
Guido van Rossum18468821994-06-20 07:49:28 +00003119static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003120_tkinter_create_impl(PyModuleDef *module, const char *screenName,
3121 const char *baseName, const char *className,
3122 int interactive, int wantobjects, int wantTk, int sync,
3123 const char *use)
3124/*[clinic end generated code: output=b8847800fc3b27eb input=c133c59a99dd0086]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003125{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003126 /* XXX baseName is not used anymore;
3127 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003128 CHECK_STRING_LENGTH(screenName);
3129 CHECK_STRING_LENGTH(baseName);
3130 CHECK_STRING_LENGTH(className);
3131 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003132
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003133 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003134 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003135 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003136}
3137
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003138/*[clinic input]
3139_tkinter.setbusywaitinterval
3140
3141 new_val: int
3142 /
3143
3144Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3145
3146It should be set to a divisor of the maximum time between frames in an animation.
3147[clinic start generated code]*/
3148
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003149static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003150_tkinter_setbusywaitinterval_impl(PyModuleDef *module, int new_val)
3151/*[clinic end generated code: output=0b9d7ef7940461ea input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003152{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003153 if (new_val < 0) {
3154 PyErr_SetString(PyExc_ValueError,
3155 "busywaitinterval must be >= 0");
3156 return NULL;
3157 }
3158 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003159 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003160}
3161
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003162/*[clinic input]
3163_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003164
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003165Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3166[clinic start generated code]*/
3167
3168static int
3169_tkinter_getbusywaitinterval_impl(PyModuleDef *module)
3170/*[clinic end generated code: output=9d09eee026e96971 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003171{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003172 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003173}
3174
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003175#include "clinic/_tkinter.c.h"
3176
3177static PyMethodDef Tktt_methods[] =
3178{
3179 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3180 {NULL, NULL}
3181};
3182
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003183static PyType_Slot Tktt_Type_slots[] = {
3184 {Py_tp_dealloc, Tktt_Dealloc},
3185 {Py_tp_repr, Tktt_Repr},
3186 {Py_tp_methods, Tktt_methods},
3187 {0, 0}
3188};
3189
3190static PyType_Spec Tktt_Type_spec = {
3191 "_tkinter.tktimertoken",
3192 sizeof(TkttObject),
3193 0,
3194 Py_TPFLAGS_DEFAULT,
3195 Tktt_Type_slots,
3196};
3197
3198
3199/**** Tkapp Method List ****/
3200
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003201static PyMethodDef Tkapp_methods[] =
3202{
3203 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3204 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3205 {"call", Tkapp_Call, METH_VARARGS},
3206 _TKINTER_TKAPP_EVAL_METHODDEF
3207 _TKINTER_TKAPP_EVALFILE_METHODDEF
3208 _TKINTER_TKAPP_RECORD_METHODDEF
3209 _TKINTER_TKAPP_ADDERRINFO_METHODDEF
3210 {"setvar", Tkapp_SetVar, METH_VARARGS},
3211 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3212 {"getvar", Tkapp_GetVar, METH_VARARGS},
3213 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3214 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3215 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3216 _TKINTER_TKAPP_GETINT_METHODDEF
3217 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3218 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3219 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3220 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3221 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3222 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3223 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3224 _TKINTER_TKAPP_SPLIT_METHODDEF
3225 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3226 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3227 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3228 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3229 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3230 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3231 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3232 _TKINTER_TKAPP_QUIT_METHODDEF
3233 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3234 _TKINTER_TKAPP_LOADTK_METHODDEF
3235 {NULL, NULL}
3236};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003237
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003238static PyType_Slot Tkapp_Type_slots[] = {
3239 {Py_tp_dealloc, Tkapp_Dealloc},
3240 {Py_tp_methods, Tkapp_methods},
3241 {0, 0}
3242};
3243
3244
3245static PyType_Spec Tkapp_Type_spec = {
3246 "_tkinter.tkapp",
3247 sizeof(TkappObject),
3248 0,
3249 Py_TPFLAGS_DEFAULT,
3250 Tkapp_Type_slots,
3251};
3252
Guido van Rossum18468821994-06-20 07:49:28 +00003253static PyMethodDef moduleMethods[] =
3254{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003255 _TKINTER__FLATTEN_METHODDEF
3256 _TKINTER_CREATE_METHODDEF
3257 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3258 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003259 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003260};
3261
Guido van Rossum7bf15641998-05-22 18:28:17 +00003262#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003263
3264static int stdin_ready = 0;
3265
Guido van Rossumad4db171998-06-13 13:56:28 +00003266#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003267static void
Fred Drake509d79a2000-07-08 04:04:38 +00003268MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003269{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003270 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003271}
Guido van Rossumad4db171998-06-13 13:56:28 +00003272#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003273
Martin v. Löwisa9656492003-03-30 08:44:58 +00003274#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003275static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003276#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003277
Guido van Rossum18468821994-06-20 07:49:28 +00003278static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003279EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003280{
Guido van Rossumad4db171998-06-13 13:56:28 +00003281#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003282 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003283#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003284#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003285 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003286#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003287 stdin_ready = 0;
3288 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003289#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003290 tfile = fileno(stdin);
3291 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003292#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003293 while (!errorInCmd && !stdin_ready) {
3294 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003295#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003296 if (_kbhit()) {
3297 stdin_ready = 1;
3298 break;
3299 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003300#endif
3301#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003302 Py_BEGIN_ALLOW_THREADS
3303 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3304 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003305
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003306 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003307
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003308 tcl_tstate = NULL;
3309 if(tcl_lock)PyThread_release_lock(tcl_lock);
3310 if (result == 0)
3311 Sleep(Tkinter_busywaitinterval);
3312 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003313#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003314 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003315#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003316
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003317 if (result < 0)
3318 break;
3319 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003320#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003321 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003322#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003323 if (errorInCmd) {
3324 errorInCmd = 0;
3325 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3326 excInCmd = valInCmd = trbInCmd = NULL;
3327 PyErr_Print();
3328 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003329#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003330 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003331#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003332 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003333}
Guido van Rossum18468821994-06-20 07:49:28 +00003334
Guido van Rossum00d93061998-05-28 23:06:38 +00003335#endif
3336
Guido van Rossum7bf15641998-05-22 18:28:17 +00003337static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003338EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003339{
Guido van Rossum00d93061998-05-28 23:06:38 +00003340#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003341 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003342#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003343 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003344#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003345 PyOS_InputHook = EventHook;
3346 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003347#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003348}
3349
3350static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003351DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003352{
Guido van Rossum00d93061998-05-28 23:06:38 +00003353#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003354 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3355 PyOS_InputHook = NULL;
3356 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003357#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003358}
3359
Barry Warsawfa701a81997-01-16 00:15:11 +00003360
Martin v. Löwis1a214512008-06-11 05:26:20 +00003361static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003362 PyModuleDef_HEAD_INIT,
3363 "_tkinter",
3364 NULL,
3365 -1,
3366 moduleMethods,
3367 NULL,
3368 NULL,
3369 NULL,
3370 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003371};
3372
Mark Hammond62b1ab12002-07-23 06:31:15 +00003373PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003374PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003375{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003376 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003377
Guido van Rossum00d93061998-05-28 23:06:38 +00003378#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003379 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003380 if (tcl_lock == NULL)
3381 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003382#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003384 m = PyModule_Create(&_tkintermodule);
3385 if (m == NULL)
3386 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003387
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003388 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3389 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003390 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003391 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003392 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003393 Py_INCREF(o);
3394 if (PyModule_AddObject(m, "TclError", o)) {
3395 Py_DECREF(o);
3396 Py_DECREF(m);
3397 return NULL;
3398 }
3399 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003400
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003401 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3402 Py_DECREF(m);
3403 return NULL;
3404 }
3405 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3406 Py_DECREF(m);
3407 return NULL;
3408 }
3409 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3410 Py_DECREF(m);
3411 return NULL;
3412 }
3413 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3414 Py_DECREF(m);
3415 return NULL;
3416 }
3417 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3418 Py_DECREF(m);
3419 return NULL;
3420 }
3421 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3422 Py_DECREF(m);
3423 return NULL;
3424 }
3425 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3426 Py_DECREF(m);
3427 return NULL;
3428 }
3429 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3430 Py_DECREF(m);
3431 return NULL;
3432 }
3433 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3434 Py_DECREF(m);
3435 return NULL;
3436 }
3437 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3438 Py_DECREF(m);
3439 return NULL;
3440 }
3441 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3442 Py_DECREF(m);
3443 return NULL;
3444 }
3445
3446 o = PyType_FromSpec(&Tkapp_Type_spec);
3447 if (o == NULL) {
3448 Py_DECREF(m);
3449 return NULL;
3450 }
3451 if (PyModule_AddObject(m, "TkappType", o)) {
3452 Py_DECREF(o);
3453 Py_DECREF(m);
3454 return NULL;
3455 }
3456 Tkapp_Type = o;
3457
3458 o = PyType_FromSpec(&Tktt_Type_spec);
3459 if (o == NULL) {
3460 Py_DECREF(m);
3461 return NULL;
3462 }
3463 if (PyModule_AddObject(m, "TkttType", o)) {
3464 Py_DECREF(o);
3465 Py_DECREF(m);
3466 return NULL;
3467 }
3468 Tktt_Type = o;
3469
3470 o = PyType_FromSpec(&PyTclObject_Type_spec);
3471 if (o == NULL) {
3472 Py_DECREF(m);
3473 return NULL;
3474 }
3475 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3476 Py_DECREF(o);
3477 Py_DECREF(m);
3478 return NULL;
3479 }
3480 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003481
3482#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003483 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3484 * start waking up. Note that Tcl_FindExecutable will do this, this
3485 * code must be above it! The original warning from
3486 * tkMacOSXAppInit.c is copied below.
3487 *
3488 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3489 * Tcl interpreter for now. It probably should work to do this
3490 * in the other order, but for now it doesn't seem to.
3491 *
3492 */
3493 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003494#endif
3495
3496
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003497 /* This helps the dynamic loader; in Unicode aware Tcl versions
3498 it also helps Tcl find its encodings. */
3499 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3500 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003501 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003502 if (cexe)
3503 Tcl_FindExecutable(PyBytes_AsString(cexe));
3504 Py_XDECREF(cexe);
3505 Py_DECREF(uexe);
3506 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003508 if (PyErr_Occurred()) {
3509 Py_DECREF(m);
3510 return NULL;
3511 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003512
Guido van Rossum43ff8681998-07-14 18:02:13 +00003513#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003514 /* This was not a good idea; through <Destroy> bindings,
3515 Tcl_Finalize() may invoke Python code but at that point the
3516 interpreter and thread state have already been destroyed! */
3517 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003518#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003519 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003520}