blob: 91d3dd583edd1e6775886e6cb02572b6d314eceb [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 Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030
Guido van Rossum2a5119b1998-05-29 01:28:40 +000031#ifdef MS_WINDOWS
32#include <windows.h>
33#endif
34
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030035#define CHECK_SIZE(size, elemsize) \
Serhiy Storchaka26861b02015-02-16 20:52:17 +020036 ((size_t)(size) <= Py_MIN((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030037
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000038/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
39 it always; if Tcl is not threaded, the thread functions in
40 Tcl are empty. */
41#define TCL_THREADS
42
Jack Jansencb852442001-12-09 23:15:56 +000043#ifdef TK_FRAMEWORK
44#include <Tcl/tcl.h>
45#include <Tk/tk.h>
46#else
Guido van Rossum18468821994-06-20 07:49:28 +000047#include <tcl.h>
48#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000049#endif
Guido van Rossum18468821994-06-20 07:49:28 +000050
Guilherme Polo2d87e422009-04-10 22:19:09 +000051#include "tkinter.h"
52
Serhiy Storchaka71b49dd2015-04-22 10:59:32 +030053#if TK_HEX_VERSION < 0x08040200
Serhiy Storchaka6716d602014-07-30 19:19:21 +030054#error "Tk older than 8.4 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000055#endif
56
Serhiy Storchaka3af7a382015-04-22 10:53:08 +030057#if TK_HEX_VERSION >= 0x08050208 && TK_HEX_VERSION < 0x08060000 || \
58 TK_HEX_VERSION >= 0x08060200
Serhiy Storchakaea134da2015-04-02 18:46:50 +030059#define HAVE_LIBTOMMAMTH
60#include <tclTomMath.h>
61#endif
62
Jack Janseneddc1442003-11-20 01:44:59 +000063#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000064#define HAVE_CREATEFILEHANDLER
65#endif
66
Guido van Rossum00d93061998-05-28 23:06:38 +000067#ifdef HAVE_CREATEFILEHANDLER
68
Neal Norwitzd948a432006-01-08 01:08:55 +000069/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
70 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
71#ifndef TCL_UNIX_FD
72# ifdef TCL_WIN_SOCKET
73# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
74# else
75# define TCL_UNIX_FD 1
76# endif
77#endif
78
Guido van Rossum00d93061998-05-28 23:06:38 +000079/* Tcl_CreateFileHandler() changed several times; these macros deal with the
80 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
81 Unix, only because Jack added it back); when available on Windows, it only
82 applies to sockets. */
83
Guido van Rossum7bf15641998-05-22 18:28:17 +000084#ifdef MS_WINDOWS
85#define FHANDLETYPE TCL_WIN_SOCKET
86#else
87#define FHANDLETYPE TCL_UNIX_FD
88#endif
89
Guido van Rossum00d93061998-05-28 23:06:38 +000090/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
91 which uses this to handle Tcl events while the user is typing commands. */
92
93#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +000094#define WAIT_FOR_STDIN
95#endif
96
Guido van Rossum00d93061998-05-28 23:06:38 +000097#endif /* HAVE_CREATEFILEHANDLER */
98
Guido van Rossumad4db171998-06-13 13:56:28 +000099#ifdef MS_WINDOWS
100#include <conio.h>
101#define WAIT_FOR_STDIN
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500102
103static PyObject *
104_get_tcl_lib_path()
105{
106 static PyObject *tcl_library_path = NULL;
107 static int already_checked = 0;
108
109 if (already_checked == 0) {
110 PyObject *prefix;
111 struct stat stat_buf;
112 int stat_return_value;
113
114 prefix = PyUnicode_FromWideChar(Py_GetPrefix(), -1);
115 if (prefix == NULL) {
116 return NULL;
117 }
118
119 /* Check expected location for an installed Python first */
120 tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION);
121 if (tcl_library_path == NULL) {
122 return NULL;
123 }
124 tcl_library_path = PyUnicode_Concat(prefix, tcl_library_path);
125 if (tcl_library_path == NULL) {
126 return NULL;
127 }
128 stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
129 if (stat_return_value == -2) {
130 return NULL;
131 }
132 if (stat_return_value == -1) {
133 /* install location doesn't exist, reset errno and see if
134 we're a repository build */
135 errno = 0;
136#ifdef Py_TCLTK_DIR
137 tcl_library_path = PyUnicode_FromString(
138 Py_TCLTK_DIR "\\lib\\tcl" TCL_VERSION);
139 if (tcl_library_path == NULL) {
140 return NULL;
141 }
142 stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
143 if (stat_return_value == -2) {
144 return NULL;
145 }
146 if (stat_return_value == -1) {
147 /* tcltkDir for a repository build doesn't exist either,
148 reset errno and leave Tcl to its own devices */
149 errno = 0;
150 tcl_library_path = NULL;
151 }
152#else
153 tcl_library_path = NULL;
Guido van Rossumad4db171998-06-13 13:56:28 +0000154#endif
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500155 }
156 already_checked = 1;
157 }
158 return tcl_library_path;
159}
160#endif /* MS_WINDOWS */
Guido van Rossumad4db171998-06-13 13:56:28 +0000161
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000162/* The threading situation is complicated. Tcl is not thread-safe, except
163 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000164
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300165 So we need to use a lock around all uses of Tcl. Previously, the
166 Python interpreter lock was used for this. However, this causes
167 problems when other Python threads need to run while Tcl is blocked
168 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000169
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300170 To solve this problem, a separate lock for Tcl is introduced.
171 Holding it is incompatible with holding Python's interpreter lock.
172 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000173
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300174 ENTER_TCL and LEAVE_TCL are brackets, just like
175 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
176 used whenever a call into Tcl is made that could call an event
177 handler, or otherwise affect the state of a Tcl interpreter. These
178 assume that the surrounding code has the Python interpreter lock;
179 inside the brackets, the Python interpreter lock has been released
180 and the lock for Tcl has been acquired.
181
182 Sometimes, it is necessary to have both the Python lock and the Tcl
183 lock. (For example, when transferring data from the Tcl
184 interpreter result to a Python string object.) This can be done by
185 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
186 reacquires the Python lock (and restores the thread state) but
187 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
188 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000189
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000190 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300191 handlers when the handler needs to use Python. Such event handlers
192 are entered while the lock for Tcl is held; the event handler
193 presumably needs to use Python. ENTER_PYTHON releases the lock for
194 Tcl and acquires the Python interpreter lock, restoring the
195 appropriate thread state, and LEAVE_PYTHON releases the Python
196 interpreter lock and re-acquires the lock for Tcl. It is okay for
197 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
198 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000199
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300200 These locks expand to several statements and brackets; they should
201 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300203 If Tcl is threaded, this approach won't work anymore. The Tcl
204 interpreter is only valid in the thread that created it, and all Tk
205 activity must happen in this thread, also. That means that the
206 mainloop must be invoked in the thread that created the
207 interpreter. Invoking commands from other threads is possible;
208 _tkinter will queue an event for the interpreter thread, which will
209 then execute the command and pass back the result. If the main
210 thread is not in the mainloop, and invoking commands causes an
211 exception; if the main loop is running but not processing events,
212 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000213
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300214 In addition, for a threaded Tcl, a single global tcl_tstate won't
215 be sufficient anymore, since multiple Tcl interpreters may
216 simultaneously dispatch in different threads. So we use the Tcl TLS
217 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000218
Guido van Rossum00d93061998-05-28 23:06:38 +0000219*/
220
Guido van Rossum65d5b571998-12-21 19:32:43 +0000221static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000222
223#ifdef TCL_THREADS
224static Tcl_ThreadDataKey state_key;
225typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300226#define tcl_tstate \
227 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000228#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000229static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000230#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000231
232#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000233 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
234 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000235
236#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300237 tcl_tstate = NULL; \
238 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000239
Guido van Rossum62320c91998-06-15 04:36:09 +0000240#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000241 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000242
243#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000244 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000245
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000246#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000247 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300248 if(tcl_lock) \
249 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000250
251#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000252 { PyThreadState *tstate = PyEval_SaveThread(); \
253 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000254
255#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000256 if (((TkappObject *)self)->threaded && \
257 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300258 PyErr_SetString(PyExc_RuntimeError, \
259 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 return 0; \
261 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000262
Guido van Rossum97867b21996-08-08 19:09:53 +0000263#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000264#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000265#endif
266
Guido van Rossum18468821994-06-20 07:49:28 +0000267/**** Tkapp Object Declaration ****/
268
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300269static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000270
Guido van Rossum00d93061998-05-28 23:06:38 +0000271typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000272 PyObject_HEAD
273 Tcl_Interp *interp;
274 int wantobjects;
275 int threaded; /* True if tcl_platform[threaded] */
276 Tcl_ThreadId thread_id;
277 int dispatching;
278 /* We cannot include tclInt.h, as this is internal.
279 So we cache interesting types here. */
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200280 const Tcl_ObjType *OldBooleanType;
Zachary Ware037605b2014-08-05 11:54:34 -0500281 const Tcl_ObjType *BooleanType;
282 const Tcl_ObjType *ByteArrayType;
283 const Tcl_ObjType *DoubleType;
284 const Tcl_ObjType *IntType;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300285 const Tcl_ObjType *WideIntType;
286 const Tcl_ObjType *BignumType;
Zachary Ware037605b2014-08-05 11:54:34 -0500287 const Tcl_ObjType *ListType;
288 const Tcl_ObjType *ProcBodyType;
289 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000290} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000291
Guido van Rossum18468821994-06-20 07:49:28 +0000292#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000293#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000294
Guido van Rossum35d43371997-08-02 00:09:09 +0000295#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000296(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000297
Barry Warsawfa701a81997-01-16 00:15:11 +0000298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000299
Guido van Rossum18468821994-06-20 07:49:28 +0000300/**** Error Handling ****/
301
302static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000303static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000304static int errorInCmd = 0;
305static PyObject *excInCmd;
306static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000307static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000308
Guilherme Polob681df42009-02-09 22:33:59 +0000309#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000310static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000311#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000313
Guido van Rossum18468821994-06-20 07:49:28 +0000314static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000315Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000316{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000317 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
318 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000319}
320
Barry Warsawfa701a81997-01-16 00:15:11 +0000321
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000322
Guido van Rossum18468821994-06-20 07:49:28 +0000323/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000324
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000325static int Tkinter_busywaitinterval = 20;
326
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000327#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000328
Guido van Rossum00d93061998-05-28 23:06:38 +0000329/* Millisecond sleep() for Unix platforms. */
330
331static void
Fred Drake509d79a2000-07-08 04:04:38 +0000332Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000333{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334 /* XXX Too bad if you don't have select(). */
335 struct timeval t;
336 t.tv_sec = milli/1000;
337 t.tv_usec = (milli%1000) * 1000;
338 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000339}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000340#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000341
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000342/* Wait up to 1s for the mainloop to come up. */
343
344static int
345WaitForMainloop(TkappObject* self)
346{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000347 int i;
348 for (i = 0; i < 10; i++) {
349 if (self->dispatching)
350 return 1;
351 Py_BEGIN_ALLOW_THREADS
352 Sleep(100);
353 Py_END_ALLOW_THREADS
354 }
355 if (self->dispatching)
356 return 1;
357 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
358 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000359}
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362
Guido van Rossum18468821994-06-20 07:49:28 +0000363#define ARGSZ 64
364
Barry Warsawfa701a81997-01-16 00:15:11 +0000365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000366
Guido van Rossum18468821994-06-20 07:49:28 +0000367static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200368unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
369{
370 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
371 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
372 /* Tcl encodes null character as \xc0\x80 */
373 if (memchr(s, '\xc0', size)) {
374 char *buf, *q;
375 const char *e = s + size;
376 PyErr_Clear();
377 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300378 if (buf == NULL) {
379 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200380 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300381 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200382 while (s != e) {
383 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
384 *q++ = '\0';
385 s += 2;
386 }
387 else
388 *q++ = *s++;
389 }
390 s = buf;
391 size = q - s;
392 r = PyUnicode_DecodeUTF8(s, size, NULL);
393 PyMem_Free(buf);
394 }
395 }
396 return r;
397}
398
399static PyObject *
400unicodeFromTclString(const char *s)
401{
402 return unicodeFromTclStringAndSize(s, strlen(s));
403}
404
405static PyObject *
406unicodeFromTclObj(Tcl_Obj *value)
407{
408 int len;
409 char *s = Tcl_GetStringFromObj(value, &len);
410 return unicodeFromTclStringAndSize(s, len);
411}
412
413
414static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300415Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000416{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000417 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300418 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000419 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000421 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300422 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 }
Guido van Rossum18468821994-06-20 07:49:28 +0000424
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000425 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
426 /* Not a list.
427 * Could be a quoted string containing funnies, e.g. {"}.
428 * Return the string itself.
429 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200430 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000431 }
Guido van Rossum18468821994-06-20 07:49:28 +0000432
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000433 if (argc == 0)
434 v = PyUnicode_FromString("");
435 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200436 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000437 else if ((v = PyTuple_New(argc)) != NULL) {
438 int i;
439 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000441 for (i = 0; i < argc; i++) {
442 if ((w = Split(argv[i])) == NULL) {
443 Py_DECREF(v);
444 v = NULL;
445 break;
446 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300447 PyTuple_SET_ITEM(v, i, w);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000448 }
449 }
450 Tcl_Free(FREECAST argv);
451 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000452}
453
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300454/* In some cases, Tcl will still return strings that are supposed to
455 be lists. SplitObj walks through a nested tuple, finding string
456 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000457
Martin v. Löwis59683e82008-06-13 07:50:45 +0000458static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000459SplitObj(PyObject *arg)
460{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 if (PyTuple_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200462 Py_ssize_t i, size;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000463 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000464
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300465 size = PyTuple_GET_SIZE(arg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 result = NULL;
467 /* Recursively invoke SplitObj for all tuple items.
468 If this does not return a new object, no action is
469 needed. */
470 for(i = 0; i < size; i++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300471 elem = PyTuple_GET_ITEM(arg, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000472 newelem = SplitObj(elem);
473 if (!newelem) {
474 Py_XDECREF(result);
475 return NULL;
476 }
477 if (!result) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200478 Py_ssize_t k;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000479 if (newelem == elem) {
480 Py_DECREF(newelem);
481 continue;
482 }
483 result = PyTuple_New(size);
484 if (!result)
485 return NULL;
486 for(k = 0; k < i; k++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300487 elem = PyTuple_GET_ITEM(arg, k);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000488 Py_INCREF(elem);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300489 PyTuple_SET_ITEM(result, k, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 }
491 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300492 PyTuple_SET_ITEM(result, i, newelem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000493 }
494 if (result)
495 return result;
496 /* Fall through, returning arg. */
497 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300498 else if (PyList_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200499 Py_ssize_t i, size;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300500 PyObject *elem, *newelem, *result;
501
502 size = PyList_GET_SIZE(arg);
503 result = PyTuple_New(size);
504 if (!result)
505 return NULL;
506 /* Recursively invoke SplitObj for all list items. */
507 for(i = 0; i < size; i++) {
508 elem = PyList_GET_ITEM(arg, i);
509 newelem = SplitObj(elem);
510 if (!newelem) {
511 Py_XDECREF(result);
512 return NULL;
513 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300514 PyTuple_SET_ITEM(result, i, newelem);
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300515 }
516 return result;
517 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300518 else if (PyUnicode_Check(arg)) {
519 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300520 const char **argv;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200521 const char *list = PyUnicode_AsUTF8(arg);
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300522
523 if (list == NULL ||
524 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
525 Py_INCREF(arg);
526 return arg;
527 }
528 Tcl_Free(FREECAST argv);
529 if (argc > 1)
530 return Split(list);
531 /* Fall through, returning arg. */
532 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 else if (PyBytes_Check(arg)) {
534 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300535 const char **argv;
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300536 char *list = PyBytes_AS_STRING(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000537
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000538 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
539 Py_INCREF(arg);
540 return arg;
541 }
542 Tcl_Free(FREECAST argv);
543 if (argc > 1)
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300544 return Split(PyBytes_AS_STRING(arg));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000545 /* Fall through, returning arg. */
546 }
547 Py_INCREF(arg);
548 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000549}
Barry Warsawfa701a81997-01-16 00:15:11 +0000550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +0300552/*[clinic input]
553module _tkinter
554class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec"
555class _tkinter.Tcl_Obj "PyTclObject *" "&PyTclObject_Type_spec"
556class _tkinter.tktimertoken "TkttObject *" "&Tktt_Type_spec"
557[clinic start generated code]*/
558/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b1ebf15c162ee229]*/
559
Guido van Rossum18468821994-06-20 07:49:28 +0000560/**** Tkapp Object ****/
561
562#ifndef WITH_APPINIT
563int
Fred Drake509d79a2000-07-08 04:04:38 +0000564Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000565{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000566 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000567
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000568 if (Tcl_Init(interp) == TCL_ERROR) {
569 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
570 return TCL_ERROR;
571 }
Guilherme Polob681df42009-02-09 22:33:59 +0000572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000573 _tkinter_skip_tk_init = Tcl_GetVar(interp,
574 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
575 if (_tkinter_skip_tk_init != NULL &&
576 strcmp(_tkinter_skip_tk_init, "1") == 0) {
577 return TCL_OK;
578 }
Guilherme Polob681df42009-02-09 22:33:59 +0000579
580#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000581 if (tk_load_failed) {
582 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
583 return TCL_ERROR;
584 }
Guilherme Polob681df42009-02-09 22:33:59 +0000585#endif
586
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000587 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000588#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000589 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000590#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
592 return TCL_ERROR;
593 }
Guilherme Polob681df42009-02-09 22:33:59 +0000594
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000595 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000596}
597#endif /* !WITH_APPINIT */
598
Guido van Rossum18468821994-06-20 07:49:28 +0000599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000600
Barry Warsawfa701a81997-01-16 00:15:11 +0000601
602/* Initialize the Tk application; see the `main' function in
603 * `tkMain.c'.
604 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000605
Thomas Wouters58d05102000-07-24 14:43:35 +0000606static void EnableEventHook(void); /* Forward */
607static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000608
Barry Warsawfa701a81997-01-16 00:15:11 +0000609static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300610Tkapp_New(const char *screenName, const char *className,
611 int interactive, int wantobjects, int wantTk, int sync,
612 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000613{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 TkappObject *v;
615 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000616
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300617 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 if (v == NULL)
619 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200620 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000621
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000622 v->interp = Tcl_CreateInterp();
623 v->wantobjects = wantobjects;
624 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
625 TCL_GLOBAL_ONLY) != NULL;
626 v->thread_id = Tcl_GetCurrentThread();
627 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000628
629#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300631 PyErr_SetString(PyExc_RuntimeError,
632 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 Py_DECREF(v);
634 return 0;
635 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000636#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 if (v->threaded && tcl_lock) {
638 /* If Tcl is threaded, we don't need the lock. */
639 PyThread_free_lock(tcl_lock);
640 tcl_lock = NULL;
641 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000642
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200643 v->OldBooleanType = Tcl_GetObjType("boolean");
644 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 v->ByteArrayType = Tcl_GetObjType("bytearray");
646 v->DoubleType = Tcl_GetObjType("double");
647 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300648 v->WideIntType = Tcl_GetObjType("wideInt");
649 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 v->ListType = Tcl_GetObjType("list");
651 v->ProcBodyType = Tcl_GetObjType("procbody");
652 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 /* Delete the 'exit' command, which can screw things up */
655 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000656
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000657 if (screenName != NULL)
658 Tcl_SetVar2(v->interp, "env", "DISPLAY",
659 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 if (interactive)
662 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
663 else
664 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200667 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 if (!argv0) {
669 PyErr_NoMemory();
670 Py_DECREF(v);
671 return NULL;
672 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200675 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
676 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200678 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000679
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000680 if (! wantTk) {
681 Tcl_SetVar(v->interp,
682 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
683 }
Guilherme Polob681df42009-02-09 22:33:59 +0000684#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 else if (tk_load_failed) {
686 Tcl_SetVar(v->interp,
687 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
688 }
Guilherme Polob681df42009-02-09 22:33:59 +0000689#endif
David Aschere2b4b322004-02-18 05:59:53 +0000690
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 /* some initial arguments need to be in argv */
692 if (sync || use) {
693 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200694 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000696 if (sync)
697 len += sizeof "-sync";
698 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200699 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000700
Victor Stinneree6c3c72014-09-11 17:50:21 +0200701 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 if (!args) {
703 PyErr_NoMemory();
704 Py_DECREF(v);
705 return NULL;
706 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000707
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000708 args[0] = '\0';
709 if (sync)
710 strcat(args, "-sync");
711 if (use) {
712 if (sync)
713 strcat(args, " ");
714 strcat(args, "-use ");
715 strcat(args, use);
716 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200719 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000721
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500722#ifdef MS_WINDOWS
723 {
724 PyObject *str_path;
725 PyObject *utf8_path;
726 DWORD ret;
727
728 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
729 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
730 str_path = _get_tcl_lib_path();
731 if (str_path == NULL && PyErr_Occurred()) {
732 return NULL;
733 }
734 if (str_path != NULL) {
735 utf8_path = PyUnicode_AsUTF8String(str_path);
736 if (utf8_path == NULL) {
737 return NULL;
738 }
739 Tcl_SetVar(v->interp,
740 "tcl_library",
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300741 PyBytes_AS_STRING(utf8_path),
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500742 TCL_GLOBAL_ONLY);
743 Py_DECREF(utf8_path);
744 }
745 }
746 }
747#endif
748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 if (Tcl_AppInit(v->interp) != TCL_OK) {
750 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000751#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752 if (wantTk) {
753 const char *_tkinter_tk_failed;
754 _tkinter_tk_failed = Tcl_GetVar(v->interp,
755 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000756
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000757 if ( _tkinter_tk_failed != NULL &&
758 strcmp(_tkinter_tk_failed, "1") == 0) {
759 tk_load_failed = 1;
760 }
761 }
Guilherme Polob681df42009-02-09 22:33:59 +0000762#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000763 Py_DECREF((PyObject *)v);
764 return (TkappObject *)result;
765 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000766
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000767 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000770}
771
Barry Warsawfa701a81997-01-16 00:15:11 +0000772
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000773static void
774Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000776{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000777 Py_BEGIN_ALLOW_THREADS;
778 Tcl_MutexLock(mutex);
779 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
780 Tcl_ThreadAlert(self->thread_id);
781 Tcl_ConditionWait(cond, mutex, NULL);
782 Tcl_MutexUnlock(mutex);
783 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000784}
785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000786
Guido van Rossum18468821994-06-20 07:49:28 +0000787/** Tcl Eval **/
788
Martin v. Löwisffad6332002-11-26 09:28:05 +0000789typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000790 PyObject_HEAD
791 Tcl_Obj *value;
792 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000793} PyTclObject;
794
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300795static PyObject *PyTclObject_Type;
796#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000797
798static PyObject *
799newPyTclObject(Tcl_Obj *arg)
800{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000801 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300802 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000803 if (self == NULL)
804 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200805 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000806 Tcl_IncrRefCount(arg);
807 self->value = arg;
808 self->string = NULL;
809 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000810}
811
812static void
813PyTclObject_dealloc(PyTclObject *self)
814{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200815 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000816 Tcl_DecrRefCount(self->value);
817 Py_XDECREF(self->string);
818 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200819 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000820}
821
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200822static const char *
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000823PyTclObject_TclString(PyObject *self)
824{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000825 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000826}
827
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000828/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000829PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000830"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000831
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000832static PyObject *
833PyTclObject_string(PyTclObject *self, void *ignored)
834{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000835 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200836 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000837 if (!self->string)
838 return NULL;
839 }
840 Py_INCREF(self->string);
841 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000842}
843
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000844static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000845PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000846{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200847 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000848 Py_INCREF(self->string);
849 return self->string;
850 }
851 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200852 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000853}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000854
Martin v. Löwisffad6332002-11-26 09:28:05 +0000855static PyObject *
856PyTclObject_repr(PyTclObject *self)
857{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300858 PyObject *repr, *str = PyTclObject_str(self, NULL);
859 if (str == NULL)
860 return NULL;
861 repr = PyUnicode_FromFormat("<%s object: %R>",
862 self->value->typePtr->name, str);
863 Py_DECREF(str);
864 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000865}
866
Mark Dickinson211c6252009-02-01 10:28:51 +0000867#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
868
869static PyObject *
870PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000871{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000872 int result;
873 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000874
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000875 /* neither argument should be NULL, unless something's gone wrong */
876 if (self == NULL || other == NULL) {
877 PyErr_BadInternalCall();
878 return NULL;
879 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000880
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 /* both arguments should be instances of PyTclObject */
882 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
883 v = Py_NotImplemented;
884 goto finished;
885 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000886
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000887 if (self == other)
888 /* fast path when self and other are identical */
889 result = 0;
890 else
891 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
892 Tcl_GetString(((PyTclObject *)other)->value));
893 /* Convert return value to a Boolean */
894 switch (op) {
895 case Py_EQ:
896 v = TEST_COND(result == 0);
897 break;
898 case Py_NE:
899 v = TEST_COND(result != 0);
900 break;
901 case Py_LE:
902 v = TEST_COND(result <= 0);
903 break;
904 case Py_GE:
905 v = TEST_COND(result >= 0);
906 break;
907 case Py_LT:
908 v = TEST_COND(result < 0);
909 break;
910 case Py_GT:
911 v = TEST_COND(result > 0);
912 break;
913 default:
914 PyErr_BadArgument();
915 return NULL;
916 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000917 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000918 Py_INCREF(v);
919 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000920}
921
Martin v. Löwis39195712003-01-04 00:33:13 +0000922PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
923
Martin v. Löwisffad6332002-11-26 09:28:05 +0000924static PyObject*
925get_typename(PyTclObject* obj, void* ignored)
926{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200927 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000928}
929
Martin v. Löwis39195712003-01-04 00:33:13 +0000930
Martin v. Löwisffad6332002-11-26 09:28:05 +0000931static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000932 {"typename", (getter)get_typename, NULL, get_typename__doc__},
933 {"string", (getter)PyTclObject_string, NULL,
934 PyTclObject_string__doc__},
935 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000936};
937
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300938static PyType_Slot PyTclObject_Type_slots[] = {
939 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
940 {Py_tp_repr, (reprfunc)PyTclObject_repr},
941 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200942 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300943 {Py_tp_richcompare, PyTclObject_richcompare},
944 {Py_tp_getset, PyTclObject_getsetlist},
945 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000946};
947
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300948static PyType_Spec PyTclObject_Type_spec = {
949 "_tkinter.Tcl_Obj",
950 sizeof(PyTclObject),
951 0,
952 Py_TPFLAGS_DEFAULT,
953 PyTclObject_Type_slots,
954};
955
956
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700957#if SIZE_MAX > INT_MAX
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300958#define CHECK_STRING_LENGTH(s) do { \
959 if (s != NULL && strlen(s) >= INT_MAX) { \
960 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
961 return NULL; \
962 } } while(0)
963#else
964#define CHECK_STRING_LENGTH(s)
965#endif
966
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300967#ifdef HAVE_LIBTOMMAMTH
968static Tcl_Obj*
969asBignumObj(PyObject *value)
970{
971 Tcl_Obj *result;
972 int neg;
973 PyObject *hexstr;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200974 const char *hexchars;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300975 mp_int bigValue;
976
977 neg = Py_SIZE(value) < 0;
978 hexstr = _PyLong_Format(value, 16);
979 if (hexstr == NULL)
980 return NULL;
981 hexchars = PyUnicode_AsUTF8(hexstr);
982 if (hexchars == NULL) {
983 Py_DECREF(hexstr);
984 return NULL;
985 }
986 hexchars += neg + 2; /* skip sign and "0x" */
987 mp_init(&bigValue);
988 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
989 mp_clear(&bigValue);
990 Py_DECREF(hexstr);
991 PyErr_NoMemory();
992 return NULL;
993 }
994 Py_DECREF(hexstr);
995 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
996 result = Tcl_NewBignumObj(&bigValue);
997 mp_clear(&bigValue);
998 if (result == NULL) {
999 PyErr_NoMemory();
1000 return NULL;
1001 }
1002 return result;
1003}
1004#endif
1005
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001006static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001007AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001008{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001009 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001010
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001011 if (PyBytes_Check(value)) {
1012 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
1013 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1014 return NULL;
1015 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +03001016 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001017 (int)PyBytes_GET_SIZE(value));
1018 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001019
1020 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001021 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001022
1023 if (PyLong_CheckExact(value)) {
1024 int overflow;
1025 long longValue;
1026#ifdef TCL_WIDE_INT_TYPE
1027 Tcl_WideInt wideValue;
1028#endif
1029 longValue = PyLong_AsLongAndOverflow(value, &overflow);
1030 if (!overflow) {
1031 return Tcl_NewLongObj(longValue);
1032 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001033 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001034 fall through to wideInt handling. */
1035#ifdef TCL_WIDE_INT_TYPE
1036 if (_PyLong_AsByteArray((PyLongObject *)value,
1037 (unsigned char *)(void *)&wideValue,
1038 sizeof(wideValue),
1039 PY_LITTLE_ENDIAN,
1040 /* signed */ 1) == 0) {
1041 return Tcl_NewWideIntObj(wideValue);
1042 }
1043 PyErr_Clear();
1044#endif
1045 /* If there is an overflow in the wideInt conversion,
1046 fall through to bignum handling. */
1047#ifdef HAVE_LIBTOMMAMTH
1048 return asBignumObj(value);
1049#endif
1050 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001051 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001052 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001053
1054 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001056
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +03001057 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001058 Tcl_Obj **argv;
1059 Py_ssize_t size, i;
1060
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001061 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001062 if (size == 0)
1063 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001064 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001065 PyErr_SetString(PyExc_OverflowError,
1066 PyTuple_Check(value) ? "tuple is too long" :
1067 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001068 return NULL;
1069 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001070 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
1071 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001072 PyErr_NoMemory();
1073 return NULL;
1074 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001075 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001076 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001077 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001078 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001079 return result;
1080 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001081
1082 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001083 void *inbuf;
1084 Py_ssize_t size;
1085 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001086 Tcl_UniChar *outbuf = NULL;
1087 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001088 size_t allocsize;
1089
1090 if (PyUnicode_READY(value) == -1)
1091 return NULL;
1092
1093 inbuf = PyUnicode_DATA(value);
1094 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001095 if (size == 0)
1096 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001097 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1098 PyErr_SetString(PyExc_OverflowError, "string is too long");
1099 return NULL;
1100 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001101 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001102 if (kind == sizeof(Tcl_UniChar))
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001103 return Tcl_NewUnicodeObj(inbuf, (int)size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001104 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001105 outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001106 /* Else overflow occurred, and we take the next exit */
1107 if (!outbuf) {
1108 PyErr_NoMemory();
1109 return NULL;
1110 }
1111 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001112 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1113 /* We cannot test for sizeof(Tcl_UniChar) directly,
1114 so we test for UTF-8 size instead. */
1115#if TCL_UTF_MAX == 3
1116 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001117 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001118 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001119 "character U+%x is above the range "
1120 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001121 ch);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001122 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001123 return NULL;
1124 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001125#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001126 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001127 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001128 result = Tcl_NewUnicodeObj(outbuf, (int)size);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001129 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001130 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001131 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001132
1133 if (PyTclObject_Check(value)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001134 Tcl_Obj *v = ((PyTclObject*)value)->value;
1135 Tcl_IncrRefCount(v);
1136 return v;
1137 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001138
1139 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001140 PyObject *v = PyObject_Str(value);
1141 if (!v)
1142 return 0;
1143 result = AsObj(v);
1144 Py_DECREF(v);
1145 return result;
1146 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001147}
1148
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001149static PyObject *
1150fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1151{
1152 int boolValue;
1153 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1154 return Tkinter_Error(tkapp);
1155 return PyBool_FromLong(boolValue);
1156}
1157
Martin v. Löwisffad6332002-11-26 09:28:05 +00001158static PyObject*
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001159fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1160{
1161 Tcl_WideInt wideValue;
1162 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001163 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1164 return PyLong_FromLongLong(wideValue);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001165 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1166 sizeof(wideValue),
1167 PY_LITTLE_ENDIAN,
1168 /* signed */ 1);
1169 }
1170 return NULL;
1171}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001172
1173#ifdef HAVE_LIBTOMMAMTH
1174static PyObject*
1175fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1176{
1177 mp_int bigValue;
1178 unsigned long numBytes;
1179 unsigned char *bytes;
1180 PyObject *res;
1181
1182 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1183 return Tkinter_Error(tkapp);
1184 numBytes = mp_unsigned_bin_size(&bigValue);
1185 bytes = PyMem_Malloc(numBytes);
1186 if (bytes == NULL) {
1187 mp_clear(&bigValue);
1188 return PyErr_NoMemory();
1189 }
1190 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1191 &numBytes) != MP_OKAY) {
1192 mp_clear(&bigValue);
1193 PyMem_Free(bytes);
1194 return PyErr_NoMemory();
1195 }
1196 res = _PyLong_FromByteArray(bytes, numBytes,
1197 /* big-endian */ 0,
1198 /* unsigned */ 0);
1199 PyMem_Free(bytes);
1200 if (res != NULL && bigValue.sign == MP_NEG) {
1201 PyObject *res2 = PyNumber_Negative(res);
1202 Py_DECREF(res);
1203 res = res2;
1204 }
1205 mp_clear(&bigValue);
1206 return res;
1207}
1208#endif
1209
Martin v. Löwisffad6332002-11-26 09:28:05 +00001210static PyObject*
1211FromObj(PyObject* tkapp, Tcl_Obj *value)
1212{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001213 PyObject *result = NULL;
1214 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001215 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001216
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001217 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001218 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001219 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001220
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001221 if (value->typePtr == app->BooleanType ||
1222 value->typePtr == app->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001223 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001224 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001225
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001226 if (value->typePtr == app->ByteArrayType) {
1227 int size;
1228 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1229 return PyBytes_FromStringAndSize(data, size);
1230 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001231
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001232 if (value->typePtr == app->DoubleType) {
1233 return PyFloat_FromDouble(value->internalRep.doubleValue);
1234 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001236 if (value->typePtr == app->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001237 long longValue;
1238 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1239 return PyLong_FromLong(longValue);
1240 /* If there is an error in the long conversion,
1241 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001242 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001243
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001244 if (value->typePtr == app->IntType ||
1245 value->typePtr == app->WideIntType) {
1246 result = fromWideIntObj(tkapp, value);
1247 if (result != NULL || PyErr_Occurred())
1248 return result;
1249 Tcl_ResetResult(interp);
1250 /* If there is an error in the wideInt conversion,
1251 fall through to bignum handling. */
1252 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001253
1254#ifdef HAVE_LIBTOMMAMTH
1255 if (value->typePtr == app->IntType ||
1256 value->typePtr == app->WideIntType ||
1257 value->typePtr == app->BignumType) {
1258 return fromBignumObj(tkapp, value);
1259 }
1260#endif
1261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001262 if (value->typePtr == app->ListType) {
1263 int size;
1264 int i, status;
1265 PyObject *elem;
1266 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001267
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001268 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001269 if (status == TCL_ERROR)
1270 return Tkinter_Error(tkapp);
1271 result = PyTuple_New(size);
1272 if (!result)
1273 return NULL;
1274 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001275 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001276 if (status == TCL_ERROR) {
1277 Py_DECREF(result);
1278 return Tkinter_Error(tkapp);
1279 }
1280 elem = FromObj(tkapp, tcl_elem);
1281 if (!elem) {
1282 Py_DECREF(result);
1283 return NULL;
1284 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001285 PyTuple_SET_ITEM(result, i, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001286 }
1287 return result;
1288 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001289
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001290 if (value->typePtr == app->ProcBodyType) {
1291 /* fall through: return tcl object. */
1292 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001293
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001294 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001295 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001296 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001297 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001298 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001299
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001300#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001301 if (app->BooleanType == NULL &&
1302 strcmp(value->typePtr->name, "booleanString") == 0) {
1303 /* booleanString type is not registered in Tcl */
1304 app->BooleanType = value->typePtr;
1305 return fromBoolean(tkapp, value);
1306 }
1307#endif
1308
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001309#ifdef HAVE_LIBTOMMAMTH
1310 if (app->BignumType == NULL &&
1311 strcmp(value->typePtr->name, "bignum") == 0) {
1312 /* bignum type is not registered in Tcl */
1313 app->BignumType = value->typePtr;
1314 return fromBignumObj(tkapp, value);
1315 }
1316#endif
1317
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001318 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001319}
1320
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001321/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001322TCL_DECLARE_MUTEX(call_mutex)
1323
1324typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 Tcl_Event ev; /* Must be first */
1326 TkappObject *self;
1327 PyObject *args;
1328 int flags;
1329 PyObject **res;
1330 PyObject **exc_type, **exc_value, **exc_tb;
1331 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001332} Tkapp_CallEvent;
1333
1334void
1335Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001336{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001337 int i;
1338 for (i = 0; i < objc; i++)
1339 Tcl_DecrRefCount(objv[i]);
1340 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001341 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001342}
Guido van Rossum18468821994-06-20 07:49:28 +00001343
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001344/* Convert Python objects to Tcl objects. This must happen in the
1345 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001346
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001347static Tcl_Obj**
1348Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1349{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001351 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 if (args == NULL)
1353 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001354
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001355 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001356 objv[0] = AsObj(args);
Serhiy Storchaka0b3ec192017-03-23 17:53:47 +02001357 if (objv[0] == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001358 goto finally;
1359 objc = 1;
1360 Tcl_IncrRefCount(objv[0]);
1361 }
1362 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001363 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001364
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001365 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001366 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001367 PyErr_SetString(PyExc_OverflowError,
1368 PyTuple_Check(args) ? "tuple is too long" :
1369 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001370 return NULL;
1371 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001372 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001373 if (objv == NULL) {
1374 PyErr_NoMemory();
1375 objc = 0;
1376 goto finally;
1377 }
1378 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001380 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001381 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001382 if (v == Py_None) {
1383 objc = i;
1384 break;
1385 }
1386 objv[i] = AsObj(v);
1387 if (!objv[i]) {
1388 /* Reset objc, so it attempts to clear
1389 objects only up to i. */
1390 objc = i;
1391 goto finally;
1392 }
1393 Tcl_IncrRefCount(objv[i]);
1394 }
1395 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001396 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001397 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001398finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001399 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001400 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001401}
Guido van Rossum212643f1998-04-29 16:22:14 +00001402
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001403/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001404
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001405static PyObject*
1406Tkapp_CallResult(TkappObject *self)
1407{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001408 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001409 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001410 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001411 /* Not sure whether the IncrRef is necessary, but something
1412 may overwrite the interpreter result while we are
1413 converting it. */
1414 Tcl_IncrRefCount(value);
1415 res = FromObj((PyObject*)self, value);
1416 Tcl_DecrRefCount(value);
1417 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001418 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001419 }
1420 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001421}
Guido van Rossum632de272000-03-29 00:19:50 +00001422
Benjamin Peterson5879d412009-03-30 14:51:56 +00001423
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001424/* Tkapp_CallProc is the event procedure that is executed in the context of
1425 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1426 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001427
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001428static int
1429Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1430{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001431 Tcl_Obj *objStore[ARGSZ];
1432 Tcl_Obj **objv;
1433 int objc;
1434 int i;
1435 ENTER_PYTHON
1436 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1437 if (!objv) {
1438 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1439 *(e->res) = NULL;
1440 }
1441 LEAVE_PYTHON
1442 if (!objv)
1443 goto done;
1444 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1445 ENTER_PYTHON
1446 if (i == TCL_ERROR) {
1447 *(e->res) = NULL;
1448 *(e->exc_type) = NULL;
1449 *(e->exc_tb) = NULL;
1450 *(e->exc_value) = PyObject_CallFunction(
1451 Tkinter_TclError, "s",
1452 Tcl_GetStringResult(e->self->interp));
1453 }
1454 else {
1455 *(e->res) = Tkapp_CallResult(e->self);
1456 }
1457 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001459 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001460done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001461 /* Wake up calling thread. */
1462 Tcl_MutexLock(&call_mutex);
1463 Tcl_ConditionNotify(e->done);
1464 Tcl_MutexUnlock(&call_mutex);
1465 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001466}
1467
Benjamin Peterson5879d412009-03-30 14:51:56 +00001468
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001469/* This is the main entry point for calling a Tcl command.
1470 It supports three cases, with regard to threading:
1471 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1472 the context of the calling thread.
1473 2. Tcl is threaded, caller of the command is in the interpreter thread:
1474 Execute the command in the calling thread. Since the Tcl lock will
1475 not be used, we can merge that with case 1.
1476 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1477 the interpreter thread. Allocation of Tcl objects needs to occur in the
1478 interpreter thread, so we ship the PyObject* args to the target thread,
1479 and perform processing there. */
1480
1481static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001482Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001483{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 Tcl_Obj *objStore[ARGSZ];
1485 Tcl_Obj **objv = NULL;
1486 int objc, i;
1487 PyObject *res = NULL;
1488 TkappObject *self = (TkappObject*)selfptr;
1489 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001490
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001491 /* If args is a single tuple, replace with contents of tuple */
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001492 if (PyTuple_GET_SIZE(args) == 1) {
1493 PyObject *item = PyTuple_GET_ITEM(args, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001494 if (PyTuple_Check(item))
1495 args = item;
1496 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001497 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1498 /* We cannot call the command directly. Instead, we must
1499 marshal the parameters to the interpreter thread. */
1500 Tkapp_CallEvent *ev;
1501 Tcl_Condition cond = NULL;
1502 PyObject *exc_type, *exc_value, *exc_tb;
1503 if (!WaitForMainloop(self))
1504 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001505 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1506 if (ev == NULL) {
1507 PyErr_NoMemory();
1508 return NULL;
1509 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1511 ev->self = self;
1512 ev->args = args;
1513 ev->res = &res;
1514 ev->exc_type = &exc_type;
1515 ev->exc_value = &exc_value;
1516 ev->exc_tb = &exc_tb;
1517 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001518
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001519 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001520
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001521 if (res == NULL) {
1522 if (exc_type)
1523 PyErr_Restore(exc_type, exc_value, exc_tb);
1524 else
1525 PyErr_SetObject(Tkinter_TclError, exc_value);
1526 }
1527 Tcl_ConditionFinalize(&cond);
1528 }
1529 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001530 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001531
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001532 objv = Tkapp_CallArgs(args, objStore, &objc);
1533 if (!objv)
1534 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001535
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001536 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001537
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001538 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001539
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001540 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001541
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001542 if (i == TCL_ERROR)
1543 Tkinter_Error(selfptr);
1544 else
1545 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001546
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001548
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001549 Tkapp_CallDeallocArgs(objv, objStore, objc);
1550 }
1551 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001552}
1553
1554
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001555/*[clinic input]
1556_tkinter.tkapp.eval
1557
1558 script: str
1559 /
1560
1561[clinic start generated code]*/
1562
Barry Warsawfa701a81997-01-16 00:15:11 +00001563static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001564_tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1565/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001566{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001567 PyObject *res = NULL;
1568 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001569
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001570 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001571 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001573 ENTER_TCL
1574 err = Tcl_Eval(Tkapp_Interp(self), script);
1575 ENTER_OVERLAP
1576 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001577 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001578 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001579 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001580 LEAVE_OVERLAP_TCL
1581 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001582}
1583
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001584/*[clinic input]
1585_tkinter.tkapp.evalfile
1586
1587 fileName: str
1588 /
1589
1590[clinic start generated code]*/
1591
Guido van Rossum18468821994-06-20 07:49:28 +00001592static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001593_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1594/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001595{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001596 PyObject *res = NULL;
1597 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001598
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001599 CHECK_STRING_LENGTH(fileName);
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 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1604 ENTER_OVERLAP
1605 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001606 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001607 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001608 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001609 LEAVE_OVERLAP_TCL
1610 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001611}
1612
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001613/*[clinic input]
1614_tkinter.tkapp.record
1615
1616 script: str
1617 /
1618
1619[clinic start generated code]*/
1620
Guido van Rossum18468821994-06-20 07:49:28 +00001621static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001622_tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1623/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001624{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001625 PyObject *res = NULL;
1626 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001627
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001628 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001629 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001631 ENTER_TCL
1632 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1633 ENTER_OVERLAP
1634 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001635 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001636 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001637 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001638 LEAVE_OVERLAP_TCL
1639 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001640}
1641
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001642/*[clinic input]
1643_tkinter.tkapp.adderrinfo
Guido van Rossum18468821994-06-20 07:49:28 +00001644
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001645 msg: str
1646 /
1647
1648[clinic start generated code]*/
1649
1650static PyObject *
1651_tkinter_tkapp_adderrinfo_impl(TkappObject *self, const char *msg)
1652/*[clinic end generated code: output=0e222ee2050eb357 input=4971399317d4c136]*/
1653{
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001654 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001655 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001656
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001657 ENTER_TCL
1658 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1659 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001660
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001661 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001662}
1663
Barry Warsawfa701a81997-01-16 00:15:11 +00001664
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001665
Guido van Rossum18468821994-06-20 07:49:28 +00001666/** Tcl Variable **/
1667
Benjamin Peterson5879d412009-03-30 14:51:56 +00001668typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1669
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001670TCL_DECLARE_MUTEX(var_mutex)
1671
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001672typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001673 Tcl_Event ev; /* must be first */
1674 PyObject *self;
1675 PyObject *args;
1676 int flags;
1677 EventFunc func;
1678 PyObject **res;
1679 PyObject **exc_type;
1680 PyObject **exc_val;
1681 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001682} VarEvent;
1683
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001684/*[python]
1685
1686class varname_converter(CConverter):
1687 type = 'const char *'
1688 converter = 'varname_converter'
1689
1690[python]*/
1691/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1692
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001693static int
1694varname_converter(PyObject *in, void *_out)
1695{
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +02001696 const char *s;
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001697 const char **out = (const char**)_out;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001698 if (PyBytes_Check(in)) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001699 if (PyBytes_GET_SIZE(in) > INT_MAX) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001700 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1701 return 0;
1702 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001703 s = PyBytes_AS_STRING(in);
1704 if (strlen(s) != (size_t)PyBytes_GET_SIZE(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001705 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001706 return 0;
1707 }
1708 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001709 return 1;
1710 }
1711 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001712 Py_ssize_t size;
1713 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001714 if (s == NULL) {
1715 return 0;
1716 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001717 if (size > INT_MAX) {
1718 PyErr_SetString(PyExc_OverflowError, "string is too long");
1719 return 0;
1720 }
Victor Stinner706768c2014-08-16 01:03:39 +02001721 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001722 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001723 return 0;
1724 }
1725 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001726 return 1;
1727 }
1728 if (PyTclObject_Check(in)) {
1729 *out = PyTclObject_TclString(in);
1730 return 1;
1731 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001732 PyErr_Format(PyExc_TypeError,
1733 "must be str, bytes or Tcl_Obj, not %.50s",
1734 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001735 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001736}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001737
Benjamin Peterson5879d412009-03-30 14:51:56 +00001738
Martin v. Löwis59683e82008-06-13 07:50:45 +00001739static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001740var_perform(VarEvent *ev)
1741{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001742 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1743 if (!*(ev->res)) {
1744 PyObject *exc, *val, *tb;
1745 PyErr_Fetch(&exc, &val, &tb);
1746 PyErr_NormalizeException(&exc, &val, &tb);
1747 *(ev->exc_type) = exc;
1748 *(ev->exc_val) = val;
Serhiy Storchaka3ec5f422016-10-28 12:14:34 +03001749 Py_XDECREF(tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001750 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001751
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001752}
1753
1754static int
1755var_proc(VarEvent* ev, int flags)
1756{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001757 ENTER_PYTHON
1758 var_perform(ev);
1759 Tcl_MutexLock(&var_mutex);
1760 Tcl_ConditionNotify(ev->cond);
1761 Tcl_MutexUnlock(&var_mutex);
1762 LEAVE_PYTHON
1763 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001764}
1765
Benjamin Peterson5879d412009-03-30 14:51:56 +00001766
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001767static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001768var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001769{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001770 TkappObject *self = (TkappObject*)selfptr;
1771 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001772 VarEvent *ev;
1773 PyObject *res, *exc_type, *exc_val;
1774 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001775
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001776 /* The current thread is not the interpreter thread. Marshal
1777 the call to the interpreter thread, then wait for
1778 completion. */
1779 if (!WaitForMainloop(self))
1780 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001781
Serhiy Storchaka07940882014-09-11 10:38:54 +03001782 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1783 if (ev == NULL) {
1784 PyErr_NoMemory();
1785 return NULL;
1786 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001787 ev->self = selfptr;
1788 ev->args = args;
1789 ev->flags = flags;
1790 ev->func = func;
1791 ev->res = &res;
1792 ev->exc_type = &exc_type;
1793 ev->exc_val = &exc_val;
1794 ev->cond = &cond;
1795 ev->ev.proc = (Tcl_EventProc*)var_proc;
1796 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1797 Tcl_ConditionFinalize(&cond);
1798 if (!res) {
1799 PyErr_SetObject(exc_type, exc_val);
1800 Py_DECREF(exc_type);
1801 Py_DECREF(exc_val);
1802 return NULL;
1803 }
1804 return res;
1805 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001806 /* Tcl is not threaded, or this is the interpreter thread. */
1807 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001808}
1809
Guido van Rossum18468821994-06-20 07:49:28 +00001810static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001811SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001812{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001813 const char *name1, *name2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001814 PyObject *newValue;
1815 PyObject *res = NULL;
1816 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001817
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001818 switch (PyTuple_GET_SIZE(args)) {
1819 case 2:
1820 if (!PyArg_ParseTuple(args, "O&O:setvar",
1821 varname_converter, &name1, &newValue))
1822 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001823 /* XXX Acquire tcl lock??? */
1824 newval = AsObj(newValue);
1825 if (newval == NULL)
1826 return NULL;
1827 ENTER_TCL
1828 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1829 newval, flags);
1830 ENTER_OVERLAP
1831 if (!ok)
1832 Tkinter_Error(self);
1833 else {
1834 res = Py_None;
1835 Py_INCREF(res);
1836 }
1837 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001838 break;
1839 case 3:
1840 if (!PyArg_ParseTuple(args, "ssO:setvar",
1841 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001842 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001843 CHECK_STRING_LENGTH(name1);
1844 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001845 /* XXX must hold tcl lock already??? */
1846 newval = AsObj(newValue);
1847 ENTER_TCL
1848 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1849 ENTER_OVERLAP
1850 if (!ok)
1851 Tkinter_Error(self);
1852 else {
1853 res = Py_None;
1854 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001855 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001856 LEAVE_OVERLAP_TCL
1857 break;
1858 default:
1859 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1860 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001861 }
1862 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001863}
1864
1865static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001866Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001867{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001868 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001869}
1870
1871static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001872Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001873{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001874 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001875}
1876
Barry Warsawfa701a81997-01-16 00:15:11 +00001877
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001878
Guido van Rossum18468821994-06-20 07:49:28 +00001879static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001880GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001881{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001882 const char *name1, *name2=NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001883 PyObject *res = NULL;
1884 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001885
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001886 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1887 varname_converter, &name1, &name2))
1888 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001889
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001890 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001891 ENTER_TCL
1892 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1893 ENTER_OVERLAP
1894 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001895 PyErr_SetString(Tkinter_TclError,
1896 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001897 } else {
1898 if (((TkappObject*)self)->wantobjects) {
1899 res = FromObj(self, tres);
1900 }
1901 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001902 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001903 }
1904 }
1905 LEAVE_OVERLAP_TCL
1906 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001907}
1908
1909static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001910Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001911{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001912 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001913}
1914
1915static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001916Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001917{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001918 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001919}
1920
Barry Warsawfa701a81997-01-16 00:15:11 +00001921
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001922
Guido van Rossum18468821994-06-20 07:49:28 +00001923static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001924UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001925{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001926 char *name1, *name2=NULL;
1927 int code;
1928 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001929
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001930 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1931 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001932
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001933 CHECK_STRING_LENGTH(name1);
1934 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001935 ENTER_TCL
1936 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1937 ENTER_OVERLAP
1938 if (code == TCL_ERROR)
1939 res = Tkinter_Error(self);
1940 else {
1941 Py_INCREF(Py_None);
1942 res = Py_None;
1943 }
1944 LEAVE_OVERLAP_TCL
1945 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001946}
1947
1948static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001949Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001950{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001951 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001952}
1953
1954static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001955Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001956{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001957 return var_invoke(UnsetVar, self, args,
1958 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001959}
1960
Barry Warsawfa701a81997-01-16 00:15:11 +00001961
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001962
Guido van Rossum18468821994-06-20 07:49:28 +00001963/** Tcl to Python **/
1964
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001965/*[clinic input]
1966_tkinter.tkapp.getint
1967
1968 arg: object
1969 /
1970
1971[clinic start generated code]*/
1972
Guido van Rossum18468821994-06-20 07:49:28 +00001973static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001974_tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
1975/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001976{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001977 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001978 Tcl_Obj *value;
1979 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00001980
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001981 if (PyLong_Check(arg)) {
1982 Py_INCREF(arg);
1983 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001984 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001985
Serhiy Storchaka645058d2015-05-06 14:00:04 +03001986 if (PyTclObject_Check(arg)) {
1987 value = ((PyTclObject*)arg)->value;
1988 Tcl_IncrRefCount(value);
1989 }
1990 else {
1991 if (!PyArg_Parse(arg, "s:getint", &s))
1992 return NULL;
1993 CHECK_STRING_LENGTH(s);
1994 value = Tcl_NewStringObj(s, -1);
1995 if (value == NULL)
1996 return Tkinter_Error((PyObject *)self);
1997 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001998 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
1999 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
2000
2001 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
2002 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
2003 */
2004#ifdef HAVE_LIBTOMMAMTH
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002005 result = fromBignumObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002006#else
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002007 result = fromWideIntObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002008#endif
2009 Tcl_DecrRefCount(value);
2010 if (result != NULL || PyErr_Occurred())
2011 return result;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002012 return Tkinter_Error((PyObject *)self);
Guido van Rossum18468821994-06-20 07:49:28 +00002013}
2014
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002015/*[clinic input]
2016_tkinter.tkapp.getdouble
2017
2018 arg: object
2019 /
2020
2021[clinic start generated code]*/
2022
Guido van Rossum18468821994-06-20 07:49:28 +00002023static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002024_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
2025/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002026{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002027 char *s;
2028 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00002029
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002030 if (PyFloat_Check(arg)) {
2031 Py_INCREF(arg);
2032 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002033 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002034
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002035 if (PyNumber_Check(arg)) {
2036 return PyNumber_Float(arg);
2037 }
2038
2039 if (PyTclObject_Check(arg)) {
2040 if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
2041 ((PyTclObject*)arg)->value,
2042 &v) == TCL_ERROR)
2043 return Tkinter_Error((PyObject *)self);
2044 return PyFloat_FromDouble(v);
2045 }
2046
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002047 if (!PyArg_Parse(arg, "s:getdouble", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002048 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002049 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002050 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002051 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002052 return PyFloat_FromDouble(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002053}
2054
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002055/*[clinic input]
2056_tkinter.tkapp.getboolean
2057
2058 arg: object
2059 /
2060
2061[clinic start generated code]*/
2062
Guido van Rossum18468821994-06-20 07:49:28 +00002063static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002064_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
2065/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002066{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002067 char *s;
2068 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002069
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002070 if (PyLong_Check(arg)) { /* int or bool */
2071 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002072 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002073
2074 if (PyTclObject_Check(arg)) {
2075 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2076 ((PyTclObject*)arg)->value,
2077 &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002078 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002079 return PyBool_FromLong(v);
2080 }
2081
2082 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002083 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002084 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002085 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002086 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002087 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002088}
2089
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002090/*[clinic input]
2091_tkinter.tkapp.exprstring
2092
2093 s: str
2094 /
2095
2096[clinic start generated code]*/
2097
Guido van Rossum18468821994-06-20 07:49:28 +00002098static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002099_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2100/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002101{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002102 PyObject *res = NULL;
2103 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002104
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002105 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002106 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002107
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002108 ENTER_TCL
2109 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2110 ENTER_OVERLAP
2111 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002112 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002113 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002114 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115 LEAVE_OVERLAP_TCL
2116 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002117}
2118
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002119/*[clinic input]
2120_tkinter.tkapp.exprlong
2121
2122 s: str
2123 /
2124
2125[clinic start generated code]*/
2126
Guido van Rossum18468821994-06-20 07:49:28 +00002127static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002128_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2129/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002130{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002131 PyObject *res = NULL;
2132 int retval;
2133 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002134
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002135 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002136 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002137
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 ENTER_TCL
2139 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2140 ENTER_OVERLAP
2141 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002142 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002143 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002144 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002145 LEAVE_OVERLAP_TCL
2146 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002147}
2148
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002149/*[clinic input]
2150_tkinter.tkapp.exprdouble
2151
2152 s: str
2153 /
2154
2155[clinic start generated code]*/
2156
Guido van Rossum18468821994-06-20 07:49:28 +00002157static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002158_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2159/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002160{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002161 PyObject *res = NULL;
2162 double v;
2163 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002164
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002165 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002166 CHECK_TCL_APPARTMENT;
2167 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2168 ENTER_TCL
2169 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2170 ENTER_OVERLAP
2171 PyFPE_END_PROTECT(retval)
2172 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002173 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002174 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002175 res = PyFloat_FromDouble(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002176 LEAVE_OVERLAP_TCL
2177 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002178}
2179
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002180/*[clinic input]
2181_tkinter.tkapp.exprboolean
2182
2183 s: str
2184 /
2185
2186[clinic start generated code]*/
2187
Guido van Rossum18468821994-06-20 07:49:28 +00002188static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002189_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2190/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002191{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002192 PyObject *res = NULL;
2193 int retval;
2194 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002195
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002196 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 CHECK_TCL_APPARTMENT;
2198 ENTER_TCL
2199 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2200 ENTER_OVERLAP
2201 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002202 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002203 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002204 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002205 LEAVE_OVERLAP_TCL
2206 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002207}
2208
Barry Warsawfa701a81997-01-16 00:15:11 +00002209
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002210
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002211/*[clinic input]
2212_tkinter.tkapp.splitlist
2213
2214 arg: object
2215 /
2216
2217[clinic start generated code]*/
2218
Guido van Rossum18468821994-06-20 07:49:28 +00002219static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002220_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2221/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002222{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002223 char *list;
2224 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002225 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002226 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002227 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002228
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002229 if (PyTclObject_Check(arg)) {
2230 int objc;
2231 Tcl_Obj **objv;
2232 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2233 ((PyTclObject*)arg)->value,
2234 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002235 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002236 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002237 if (!(v = PyTuple_New(objc)))
2238 return NULL;
2239 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002240 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002241 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002242 Py_DECREF(v);
2243 return NULL;
2244 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002245 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002246 }
2247 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002248 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002249 if (PyTuple_Check(arg)) {
2250 Py_INCREF(arg);
2251 return arg;
2252 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002253 if (PyList_Check(arg)) {
2254 return PySequence_Tuple(arg);
2255 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002256
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002257 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002258 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002259
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002260 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002261 if (Tcl_SplitList(Tkapp_Interp(self), list,
2262 &argc, &argv) == TCL_ERROR) {
2263 PyMem_Free(list);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002264 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002265 }
Guido van Rossum18468821994-06-20 07:49:28 +00002266
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002267 if (!(v = PyTuple_New(argc)))
2268 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002270 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002271 PyObject *s = unicodeFromTclString(argv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002272 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002273 Py_DECREF(v);
2274 v = NULL;
2275 goto finally;
2276 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002277 PyTuple_SET_ITEM(v, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002278 }
Guido van Rossum18468821994-06-20 07:49:28 +00002279
Barry Warsawfa701a81997-01-16 00:15:11 +00002280 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002281 ckfree(FREECAST argv);
2282 PyMem_Free(list);
2283 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002284}
2285
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002286/*[clinic input]
2287_tkinter.tkapp.split
2288
2289 arg: object
2290 /
2291
2292[clinic start generated code]*/
2293
Guido van Rossum18468821994-06-20 07:49:28 +00002294static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002295_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2296/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002297{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002298 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002300
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002301 if (PyTclObject_Check(arg)) {
2302 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2303 int objc;
2304 Tcl_Obj **objv;
2305 int i;
2306 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2307 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002308 return FromObj((PyObject*)self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002309 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002310 if (objc == 0)
2311 return PyUnicode_FromString("");
2312 if (objc == 1)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002313 return FromObj((PyObject*)self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002314 if (!(v = PyTuple_New(objc)))
2315 return NULL;
2316 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002317 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002318 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002319 Py_DECREF(v);
2320 return NULL;
2321 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002322 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002323 }
2324 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002325 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002326 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002327 return SplitObj(arg);
2328
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002329 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002330 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002331 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002332 v = Split(list);
2333 PyMem_Free(list);
2334 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002335}
2336
Barry Warsawfa701a81997-01-16 00:15:11 +00002337
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002338
Guido van Rossum18468821994-06-20 07:49:28 +00002339/** Tcl Command **/
2340
Guido van Rossum00d93061998-05-28 23:06:38 +00002341/* Client data struct */
2342typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002343 PyObject *self;
2344 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002345} PythonCmd_ClientData;
2346
2347static int
Fred Drake509d79a2000-07-08 04:04:38 +00002348PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002349{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002350 errorInCmd = 1;
2351 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2352 LEAVE_PYTHON
2353 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002354}
2355
Guido van Rossum18468821994-06-20 07:49:28 +00002356/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002357 * function or method.
2358 */
Guido van Rossum18468821994-06-20 07:49:28 +00002359static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002360PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002361{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002362 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002363 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002364 int i, rv;
2365 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002366
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002367 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002368
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002369 /* TBD: no error checking here since we know, via the
2370 * Tkapp_CreateCommand() that the client data is a two-tuple
2371 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002372 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002373
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002374 /* Create argument list (argv1, ..., argvN) */
2375 if (!(arg = PyTuple_New(argc - 1)))
2376 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002377
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002378 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002379 PyObject *s = unicodeFromTclString(argv[i + 1]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002380 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002381 Py_DECREF(arg);
2382 return PythonCmd_Error(interp);
2383 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002384 PyTuple_SET_ITEM(arg, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002385 }
INADA Naoki72dccde2017-02-16 09:26:01 +09002386 res = PyObject_Call(func, arg, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002387 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002389 if (res == NULL)
2390 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002392 obj_res = AsObj(res);
2393 if (obj_res == NULL) {
2394 Py_DECREF(res);
2395 return PythonCmd_Error(interp);
2396 }
2397 else {
2398 Tcl_SetObjResult(interp, obj_res);
2399 rv = TCL_OK;
2400 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002401
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002402 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002403
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002404 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002405
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002406 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002407}
2408
2409static void
Fred Drake509d79a2000-07-08 04:04:38 +00002410PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002411{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002412 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002413
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002414 ENTER_PYTHON
2415 Py_XDECREF(data->self);
2416 Py_XDECREF(data->func);
2417 PyMem_DEL(data);
2418 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002419}
2420
Barry Warsawfa701a81997-01-16 00:15:11 +00002421
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002422
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002423
2424TCL_DECLARE_MUTEX(command_mutex)
2425
2426typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002427 Tcl_Event ev;
2428 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002429 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002430 int create;
2431 int *status;
2432 ClientData *data;
2433 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002434} CommandEvent;
2435
2436static int
2437Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002438{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002439 if (ev->create)
2440 *ev->status = Tcl_CreateCommand(
2441 ev->interp, ev->name, PythonCmd,
2442 ev->data, PythonCmdDelete) == NULL;
2443 else
2444 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2445 Tcl_MutexLock(&command_mutex);
2446 Tcl_ConditionNotify(ev->done);
2447 Tcl_MutexUnlock(&command_mutex);
2448 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002449}
2450
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002451/*[clinic input]
2452_tkinter.tkapp.createcommand
2453
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002454 name: str
2455 func: object
2456 /
2457
2458[clinic start generated code]*/
2459
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002460static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002461_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2462 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002463/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002464{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002465 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002466 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002467
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002468 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002469 if (!PyCallable_Check(func)) {
2470 PyErr_SetString(PyExc_TypeError, "command not callable");
2471 return NULL;
2472 }
Guido van Rossum18468821994-06-20 07:49:28 +00002473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002474 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2475 !WaitForMainloop(self))
2476 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002477
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002478 data = PyMem_NEW(PythonCmd_ClientData, 1);
2479 if (!data)
2480 return PyErr_NoMemory();
2481 Py_INCREF(self);
2482 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002483 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002484 data->func = func;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002485 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2486 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002487 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2488 if (ev == NULL) {
2489 PyErr_NoMemory();
2490 PyMem_DEL(data);
2491 return NULL;
2492 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002493 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2494 ev->interp = self->interp;
2495 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002496 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002497 ev->data = (ClientData)data;
2498 ev->status = &err;
2499 ev->done = &cond;
2500 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2501 Tcl_ConditionFinalize(&cond);
2502 }
2503 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002504 {
2505 ENTER_TCL
2506 err = Tcl_CreateCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002507 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 (ClientData)data, PythonCmdDelete) == NULL;
2509 LEAVE_TCL
2510 }
2511 if (err) {
2512 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2513 PyMem_DEL(data);
2514 return NULL;
2515 }
Guido van Rossum18468821994-06-20 07:49:28 +00002516
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002517 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002518}
2519
Barry Warsawfa701a81997-01-16 00:15:11 +00002520
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002521
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002522/*[clinic input]
2523_tkinter.tkapp.deletecommand
2524
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002525 name: str
2526 /
2527
2528[clinic start generated code]*/
2529
Guido van Rossum18468821994-06-20 07:49:28 +00002530static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002531_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002532/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002533{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002534 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002535
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002536 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002537
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002538 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2539 Tcl_Condition cond = NULL;
2540 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002541 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2542 if (ev == NULL) {
2543 PyErr_NoMemory();
2544 return NULL;
2545 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002546 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2547 ev->interp = self->interp;
2548 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002549 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002550 ev->status = &err;
2551 ev->done = &cond;
2552 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2553 &command_mutex);
2554 Tcl_ConditionFinalize(&cond);
2555 }
2556 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002557 {
2558 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002559 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560 LEAVE_TCL
2561 }
2562 if (err == -1) {
2563 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2564 return NULL;
2565 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002566 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002567}
2568
Barry Warsawfa701a81997-01-16 00:15:11 +00002569
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002570
Guido van Rossum00d93061998-05-28 23:06:38 +00002571#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002572/** File Handler **/
2573
Guido van Rossum00d93061998-05-28 23:06:38 +00002574typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002575 PyObject *func;
2576 PyObject *file;
2577 int id;
2578 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002579} FileHandler_ClientData;
2580
2581static FileHandler_ClientData *HeadFHCD;
2582
2583static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002584NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002585{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002586 FileHandler_ClientData *p;
2587 p = PyMem_NEW(FileHandler_ClientData, 1);
2588 if (p != NULL) {
2589 Py_XINCREF(func);
2590 Py_XINCREF(file);
2591 p->func = func;
2592 p->file = file;
2593 p->id = id;
2594 p->next = HeadFHCD;
2595 HeadFHCD = p;
2596 }
2597 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002598}
2599
2600static void
Fred Drake509d79a2000-07-08 04:04:38 +00002601DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002602{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002603 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002605 pp = &HeadFHCD;
2606 while ((p = *pp) != NULL) {
2607 if (p->id == id) {
2608 *pp = p->next;
2609 Py_XDECREF(p->func);
2610 Py_XDECREF(p->file);
2611 PyMem_DEL(p);
2612 }
2613 else
2614 pp = &p->next;
2615 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002616}
2617
Guido van Rossuma597dde1995-01-10 20:56:29 +00002618static void
Fred Drake509d79a2000-07-08 04:04:38 +00002619FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002620{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002621 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
INADA Naoki72dccde2017-02-16 09:26:01 +09002622 PyObject *func, *file, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002623
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002624 ENTER_PYTHON
2625 func = data->func;
2626 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002627
INADA Naoki72dccde2017-02-16 09:26:01 +09002628 res = PyObject_CallFunction(func, "Oi", file, mask);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002629 if (res == NULL) {
2630 errorInCmd = 1;
2631 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2632 }
2633 Py_XDECREF(res);
2634 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002635}
2636
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002637/*[clinic input]
2638_tkinter.tkapp.createfilehandler
2639
2640 file: object
2641 mask: int
2642 func: object
2643 /
2644
2645[clinic start generated code]*/
2646
Guido van Rossum18468821994-06-20 07:49:28 +00002647static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002648_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2649 int mask, PyObject *func)
2650/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002651{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002652 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002653 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002654
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002655 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002656
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002657 tfile = PyObject_AsFileDescriptor(file);
2658 if (tfile < 0)
2659 return NULL;
2660 if (!PyCallable_Check(func)) {
2661 PyErr_SetString(PyExc_TypeError, "bad argument list");
2662 return NULL;
2663 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002664
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002665 data = NewFHCD(func, file, tfile);
2666 if (data == NULL)
2667 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002669 /* Ought to check for null Tcl_File object... */
2670 ENTER_TCL
2671 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2672 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002673 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002674}
2675
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002676/*[clinic input]
2677_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002678
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002679 file: object
2680 /
2681
2682[clinic start generated code]*/
2683
2684static PyObject *
2685_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2686/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2687{
2688 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002689
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002690 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002691
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002692 tfile = PyObject_AsFileDescriptor(file);
2693 if (tfile < 0)
2694 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002696 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002697
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002698 /* Ought to check for null Tcl_File object... */
2699 ENTER_TCL
2700 Tcl_DeleteFileHandler(tfile);
2701 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002702 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002703}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002704#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002705
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002706
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002707/**** Tktt Object (timer token) ****/
2708
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002709static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002710
Guido van Rossum00d93061998-05-28 23:06:38 +00002711typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002712 PyObject_HEAD
2713 Tcl_TimerToken token;
2714 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002715} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002716
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002717/*[clinic input]
2718_tkinter.tktimertoken.deletetimerhandler
2719
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002720[clinic start generated code]*/
2721
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002722static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002723_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002724/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002725{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002726 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002727 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002728
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002729 if (v->token != NULL) {
2730 Tcl_DeleteTimerHandler(v->token);
2731 v->token = NULL;
2732 }
2733 if (func != NULL) {
2734 v->func = NULL;
2735 Py_DECREF(func);
2736 Py_DECREF(v); /* See Tktt_New() */
2737 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002738 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002739}
2740
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002741static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002742Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002743{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002744 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002745
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002746 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002747 if (v == NULL)
2748 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002749 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002750
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002751 Py_INCREF(func);
2752 v->token = NULL;
2753 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002754
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002755 /* Extra reference, deleted when called or when handler is deleted */
2756 Py_INCREF(v);
2757 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002758}
2759
2760static void
Fred Drake509d79a2000-07-08 04:04:38 +00002761Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002762{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002763 TkttObject *v = (TkttObject *)self;
2764 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002765 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002766
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002767 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002769 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002770 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002771}
2772
Guido van Rossum597ac201998-05-12 14:36:19 +00002773static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002774Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002775{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002776 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002777 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2778 v,
2779 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002780}
2781
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002782/** Timer Handler **/
2783
2784static void
Fred Drake509d79a2000-07-08 04:04:38 +00002785TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002786{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002787 TkttObject *v = (TkttObject *)clientData;
2788 PyObject *func = v->func;
2789 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002790
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002791 if (func == NULL)
2792 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002793
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002795
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002796 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002797
INADA Naoki72dccde2017-02-16 09:26:01 +09002798 res = _PyObject_CallNoArg(func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002799 Py_DECREF(func);
2800 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002801
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002802 if (res == NULL) {
2803 errorInCmd = 1;
2804 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2805 }
2806 else
2807 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002808
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002809 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002810}
2811
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002812/*[clinic input]
2813_tkinter.tkapp.createtimerhandler
2814
2815 milliseconds: int
2816 func: object
2817 /
2818
2819[clinic start generated code]*/
2820
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002821static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002822_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2823 PyObject *func)
2824/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002825{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002826 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002827
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002828 if (!PyCallable_Check(func)) {
2829 PyErr_SetString(PyExc_TypeError, "bad argument list");
2830 return NULL;
2831 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002832
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002833 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002834
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002835 v = Tktt_New(func);
2836 if (v) {
2837 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2838 (ClientData)v);
2839 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002840
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002841 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002842}
2843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002844
Guido van Rossum18468821994-06-20 07:49:28 +00002845/** Event Loop **/
2846
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002847/*[clinic input]
2848_tkinter.tkapp.mainloop
2849
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002850 threshold: int = 0
2851 /
2852
2853[clinic start generated code]*/
2854
Guido van Rossum18468821994-06-20 07:49:28 +00002855static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002856_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002857/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002858{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002859 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002860
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002861 CHECK_TCL_APPARTMENT;
2862 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002863
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002864 quitMainLoop = 0;
2865 while (Tk_GetNumMainWindows() > threshold &&
2866 !quitMainLoop &&
2867 !errorInCmd)
2868 {
2869 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002870
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002871 if (self->threaded) {
2872 /* Allow other Python threads to run. */
2873 ENTER_TCL
2874 result = Tcl_DoOneEvent(0);
2875 LEAVE_TCL
2876 }
2877 else {
2878 Py_BEGIN_ALLOW_THREADS
2879 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2880 tcl_tstate = tstate;
2881 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2882 tcl_tstate = NULL;
2883 if(tcl_lock)PyThread_release_lock(tcl_lock);
2884 if (result == 0)
2885 Sleep(Tkinter_busywaitinterval);
2886 Py_END_ALLOW_THREADS
2887 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002888
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002889 if (PyErr_CheckSignals() != 0) {
2890 self->dispatching = 0;
2891 return NULL;
2892 }
2893 if (result < 0)
2894 break;
2895 }
2896 self->dispatching = 0;
2897 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002898
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002899 if (errorInCmd) {
2900 errorInCmd = 0;
2901 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2902 excInCmd = valInCmd = trbInCmd = NULL;
2903 return NULL;
2904 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002905 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002906}
2907
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002908/*[clinic input]
2909_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002910
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002911 flags: int = 0
2912 /
2913
2914[clinic start generated code]*/
2915
2916static PyObject *
2917_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2918/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2919{
2920 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002921
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002922 ENTER_TCL
2923 rv = Tcl_DoOneEvent(flags);
2924 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002925 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002926}
2927
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002928/*[clinic input]
2929_tkinter.tkapp.quit
2930[clinic start generated code]*/
2931
Guido van Rossum062cfb01995-01-10 17:42:51 +00002932static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002933_tkinter_tkapp_quit_impl(TkappObject *self)
2934/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002935{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002936 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002937 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002938}
2939
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002940/*[clinic input]
2941_tkinter.tkapp.interpaddr
2942[clinic start generated code]*/
2943
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002944static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002945_tkinter_tkapp_interpaddr_impl(TkappObject *self)
2946/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002947{
Victor Stinnere1040e22013-09-05 00:22:24 +02002948 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002949}
2950
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002951/*[clinic input]
2952_tkinter.tkapp.loadtk
2953[clinic start generated code]*/
2954
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002955static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002956_tkinter_tkapp_loadtk_impl(TkappObject *self)
2957/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00002958{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002959 Tcl_Interp *interp = Tkapp_Interp(self);
2960 const char * _tk_exists = NULL;
2961 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002962
Guilherme Polob681df42009-02-09 22:33:59 +00002963#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002964 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2965 * first call failed.
2966 * To avoid the deadlock, we just refuse the second call through
2967 * a static variable.
2968 */
2969 if (tk_load_failed) {
2970 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2971 return NULL;
2972 }
Guilherme Polob681df42009-02-09 22:33:59 +00002973#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002974
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002975 /* We want to guard against calling Tk_Init() multiple times */
2976 CHECK_TCL_APPARTMENT;
2977 ENTER_TCL
2978 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2979 ENTER_OVERLAP
2980 if (err == TCL_ERROR) {
2981 /* This sets an exception, but we cannot return right
2982 away because we need to exit the overlap first. */
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002983 Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002984 } else {
2985 _tk_exists = Tkapp_Result(self);
2986 }
2987 LEAVE_OVERLAP_TCL
2988 if (err == TCL_ERROR) {
2989 return NULL;
2990 }
2991 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2992 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002993 PyErr_SetString(Tkinter_TclError,
2994 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002995#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002996 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002997#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002998 return NULL;
2999 }
3000 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003001 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00003002}
Barry Warsawfa701a81997-01-16 00:15:11 +00003003
Martin v. Löwisffad6332002-11-26 09:28:05 +00003004static PyObject *
3005Tkapp_WantObjects(PyObject *self, PyObject *args)
3006{
3007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003008 int wantobjects = -1;
3009 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3010 return NULL;
3011 if (wantobjects == -1)
3012 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3013 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003014
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003015 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003016}
3017
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003018/*[clinic input]
3019_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003020
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003021[clinic start generated code]*/
3022
3023static PyObject *
3024_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03003025/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003026{
3027 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003028
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003029 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003030}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003031
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003032
Guido van Rossum18468821994-06-20 07:49:28 +00003033/**** Tkapp Type Methods ****/
3034
3035static void
Fred Drake509d79a2000-07-08 04:04:38 +00003036Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003037{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003038 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003039 /*CHECK_TCL_APPARTMENT;*/
3040 ENTER_TCL
3041 Tcl_DeleteInterp(Tkapp_Interp(self));
3042 LEAVE_TCL
3043 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003044 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003045 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003046}
3047
Barry Warsawfa701a81997-01-16 00:15:11 +00003048
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003049
Guido van Rossum18468821994-06-20 07:49:28 +00003050/**** Tkinter Module ****/
3051
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003052typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003053 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003054 Py_ssize_t size; /* current size */
3055 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003056} FlattenContext;
3057
3058static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003059_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003060{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003061 /* expand tuple to hold (at least) size new items.
3062 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003063
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003064 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003065
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003066 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003067 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003068
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003069 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003071 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003072}
3073
3074static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003075_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003076{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003077 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003078
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003079 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003080
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003081 if (depth > 1000) {
3082 PyErr_SetString(PyExc_ValueError,
3083 "nesting too deep in _flatten");
3084 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003085 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3086 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003087 /* preallocate (assume no nesting) */
3088 if (context->size + size > context->maxsize &&
3089 !_bump(context, size))
3090 return 0;
3091 /* copy items to output tuple */
3092 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003093 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003094 if (PyList_Check(o) || PyTuple_Check(o)) {
3095 if (!_flatten1(context, o, depth + 1))
3096 return 0;
3097 } else if (o != Py_None) {
3098 if (context->size + 1 > context->maxsize &&
3099 !_bump(context, 1))
3100 return 0;
3101 Py_INCREF(o);
3102 PyTuple_SET_ITEM(context->tuple,
3103 context->size++, o);
3104 }
3105 }
3106 } else {
3107 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3108 return 0;
3109 }
3110 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003111}
3112
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003113/*[clinic input]
3114_tkinter._flatten
3115
3116 item: object
3117 /
3118
3119[clinic start generated code]*/
3120
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003121static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003122_tkinter__flatten(PyObject *module, PyObject *item)
3123/*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003124{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003125 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003126
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003127 context.maxsize = PySequence_Size(item);
3128 if (context.maxsize < 0)
3129 return NULL;
3130 if (context.maxsize == 0)
3131 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003132
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003133 context.tuple = PyTuple_New(context.maxsize);
3134 if (!context.tuple)
3135 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003136
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003137 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003138
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003139 if (!_flatten1(&context, item,0))
3140 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003141
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003142 if (_PyTuple_Resize(&context.tuple, context.size))
3143 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003144
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003145 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003146}
3147
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003148/*[clinic input]
3149_tkinter.create
3150
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003151 screenName: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003152 baseName: str = NULL
3153 className: str = "Tk"
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003154 interactive: bool(accept={int}) = False
3155 wantobjects: bool(accept={int}) = False
3156 wantTk: bool(accept={int}) = True
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003157 if false, then Tk_Init() doesn't get called
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003158 sync: bool(accept={int}) = False
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003159 if true, then pass -sync to wish
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003160 use: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003161 if not None, then pass -use to wish
3162 /
3163
3164[clinic start generated code]*/
3165
Guido van Rossum18468821994-06-20 07:49:28 +00003166static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003167_tkinter_create_impl(PyObject *module, const char *screenName,
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003168 const char *baseName, const char *className,
3169 int interactive, int wantobjects, int wantTk, int sync,
3170 const char *use)
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003171/*[clinic end generated code: output=e3315607648e6bb4 input=431907c134c80085]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003172{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003173 /* XXX baseName is not used anymore;
3174 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003175 CHECK_STRING_LENGTH(screenName);
3176 CHECK_STRING_LENGTH(baseName);
3177 CHECK_STRING_LENGTH(className);
3178 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003179
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003180 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003181 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003182 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003183}
3184
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003185/*[clinic input]
3186_tkinter.setbusywaitinterval
3187
3188 new_val: int
3189 /
3190
3191Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3192
3193It should be set to a divisor of the maximum time between frames in an animation.
3194[clinic start generated code]*/
3195
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003196static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003197_tkinter_setbusywaitinterval_impl(PyObject *module, int new_val)
3198/*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003199{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003200 if (new_val < 0) {
3201 PyErr_SetString(PyExc_ValueError,
3202 "busywaitinterval must be >= 0");
3203 return NULL;
3204 }
3205 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003206 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003207}
3208
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003209/*[clinic input]
3210_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003211
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003212Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3213[clinic start generated code]*/
3214
3215static int
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003216_tkinter_getbusywaitinterval_impl(PyObject *module)
3217/*[clinic end generated code: output=23b72d552001f5c7 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003218{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003219 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003220}
3221
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003222#include "clinic/_tkinter.c.h"
3223
3224static PyMethodDef Tktt_methods[] =
3225{
3226 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3227 {NULL, NULL}
3228};
3229
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003230static PyType_Slot Tktt_Type_slots[] = {
3231 {Py_tp_dealloc, Tktt_Dealloc},
3232 {Py_tp_repr, Tktt_Repr},
3233 {Py_tp_methods, Tktt_methods},
3234 {0, 0}
3235};
3236
3237static PyType_Spec Tktt_Type_spec = {
3238 "_tkinter.tktimertoken",
3239 sizeof(TkttObject),
3240 0,
3241 Py_TPFLAGS_DEFAULT,
3242 Tktt_Type_slots,
3243};
3244
3245
3246/**** Tkapp Method List ****/
3247
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003248static PyMethodDef Tkapp_methods[] =
3249{
3250 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3251 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3252 {"call", Tkapp_Call, METH_VARARGS},
3253 _TKINTER_TKAPP_EVAL_METHODDEF
3254 _TKINTER_TKAPP_EVALFILE_METHODDEF
3255 _TKINTER_TKAPP_RECORD_METHODDEF
3256 _TKINTER_TKAPP_ADDERRINFO_METHODDEF
3257 {"setvar", Tkapp_SetVar, METH_VARARGS},
3258 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3259 {"getvar", Tkapp_GetVar, METH_VARARGS},
3260 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3261 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3262 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3263 _TKINTER_TKAPP_GETINT_METHODDEF
3264 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3265 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3266 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3267 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3268 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3269 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3270 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3271 _TKINTER_TKAPP_SPLIT_METHODDEF
3272 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3273 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3274 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3275 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3276 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3277 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3278 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3279 _TKINTER_TKAPP_QUIT_METHODDEF
3280 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3281 _TKINTER_TKAPP_LOADTK_METHODDEF
3282 {NULL, NULL}
3283};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003284
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003285static PyType_Slot Tkapp_Type_slots[] = {
3286 {Py_tp_dealloc, Tkapp_Dealloc},
3287 {Py_tp_methods, Tkapp_methods},
3288 {0, 0}
3289};
3290
3291
3292static PyType_Spec Tkapp_Type_spec = {
3293 "_tkinter.tkapp",
3294 sizeof(TkappObject),
3295 0,
3296 Py_TPFLAGS_DEFAULT,
3297 Tkapp_Type_slots,
3298};
3299
Guido van Rossum18468821994-06-20 07:49:28 +00003300static PyMethodDef moduleMethods[] =
3301{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003302 _TKINTER__FLATTEN_METHODDEF
3303 _TKINTER_CREATE_METHODDEF
3304 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3305 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003306 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003307};
3308
Guido van Rossum7bf15641998-05-22 18:28:17 +00003309#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003310
3311static int stdin_ready = 0;
3312
Guido van Rossumad4db171998-06-13 13:56:28 +00003313#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003314static void
Fred Drake509d79a2000-07-08 04:04:38 +00003315MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003316{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003317 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003318}
Guido van Rossumad4db171998-06-13 13:56:28 +00003319#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003320
Guido van Rossum00d93061998-05-28 23:06:38 +00003321static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003322
Guido van Rossum18468821994-06-20 07:49:28 +00003323static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003324EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003325{
Guido van Rossumad4db171998-06-13 13:56:28 +00003326#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003327 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003328#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003329 PyEval_RestoreThread(event_tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003330 stdin_ready = 0;
3331 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003332#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003333 tfile = fileno(stdin);
3334 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003335#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003336 while (!errorInCmd && !stdin_ready) {
3337 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003338#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003339 if (_kbhit()) {
3340 stdin_ready = 1;
3341 break;
3342 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003343#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003344 Py_BEGIN_ALLOW_THREADS
3345 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3346 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003348 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003350 tcl_tstate = NULL;
3351 if(tcl_lock)PyThread_release_lock(tcl_lock);
3352 if (result == 0)
3353 Sleep(Tkinter_busywaitinterval);
3354 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003356 if (result < 0)
3357 break;
3358 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003359#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003360 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003361#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003362 if (errorInCmd) {
3363 errorInCmd = 0;
3364 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3365 excInCmd = valInCmd = trbInCmd = NULL;
3366 PyErr_Print();
3367 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003368 PyEval_SaveThread();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003369 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003370}
Guido van Rossum18468821994-06-20 07:49:28 +00003371
Guido van Rossum00d93061998-05-28 23:06:38 +00003372#endif
3373
Guido van Rossum7bf15641998-05-22 18:28:17 +00003374static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003375EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003376{
Guido van Rossum00d93061998-05-28 23:06:38 +00003377#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003378 if (PyOS_InputHook == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003379 event_tstate = PyThreadState_Get();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003380 PyOS_InputHook = EventHook;
3381 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003382#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003383}
3384
3385static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003386DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003387{
Guido van Rossum00d93061998-05-28 23:06:38 +00003388#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003389 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3390 PyOS_InputHook = NULL;
3391 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003392#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003393}
3394
Barry Warsawfa701a81997-01-16 00:15:11 +00003395
Martin v. Löwis1a214512008-06-11 05:26:20 +00003396static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003397 PyModuleDef_HEAD_INIT,
3398 "_tkinter",
3399 NULL,
3400 -1,
3401 moduleMethods,
3402 NULL,
3403 NULL,
3404 NULL,
3405 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003406};
3407
Mark Hammond62b1ab12002-07-23 06:31:15 +00003408PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003409PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003410{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003411 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003413 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003414 if (tcl_lock == NULL)
3415 return NULL;
Guido van Rossumae92f011996-08-21 19:03:36 +00003416
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003417 m = PyModule_Create(&_tkintermodule);
3418 if (m == NULL)
3419 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003420
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003421 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3422 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003423 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003424 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003425 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003426 Py_INCREF(o);
3427 if (PyModule_AddObject(m, "TclError", o)) {
3428 Py_DECREF(o);
3429 Py_DECREF(m);
3430 return NULL;
3431 }
3432 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003433
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003434 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3435 Py_DECREF(m);
3436 return NULL;
3437 }
3438 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3439 Py_DECREF(m);
3440 return NULL;
3441 }
3442 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3443 Py_DECREF(m);
3444 return NULL;
3445 }
3446 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3447 Py_DECREF(m);
3448 return NULL;
3449 }
3450 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3451 Py_DECREF(m);
3452 return NULL;
3453 }
3454 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3455 Py_DECREF(m);
3456 return NULL;
3457 }
3458 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3459 Py_DECREF(m);
3460 return NULL;
3461 }
3462 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3463 Py_DECREF(m);
3464 return NULL;
3465 }
3466 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3467 Py_DECREF(m);
3468 return NULL;
3469 }
3470 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3471 Py_DECREF(m);
3472 return NULL;
3473 }
3474 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3475 Py_DECREF(m);
3476 return NULL;
3477 }
3478
3479 o = PyType_FromSpec(&Tkapp_Type_spec);
3480 if (o == NULL) {
3481 Py_DECREF(m);
3482 return NULL;
3483 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003484 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003485 if (PyModule_AddObject(m, "TkappType", o)) {
3486 Py_DECREF(o);
3487 Py_DECREF(m);
3488 return NULL;
3489 }
3490 Tkapp_Type = o;
3491
3492 o = PyType_FromSpec(&Tktt_Type_spec);
3493 if (o == NULL) {
3494 Py_DECREF(m);
3495 return NULL;
3496 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003497 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003498 if (PyModule_AddObject(m, "TkttType", o)) {
3499 Py_DECREF(o);
3500 Py_DECREF(m);
3501 return NULL;
3502 }
3503 Tktt_Type = o;
3504
3505 o = PyType_FromSpec(&PyTclObject_Type_spec);
3506 if (o == NULL) {
3507 Py_DECREF(m);
3508 return NULL;
3509 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003510 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003511 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3512 Py_DECREF(o);
3513 Py_DECREF(m);
3514 return NULL;
3515 }
3516 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003517
3518#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003519 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3520 * start waking up. Note that Tcl_FindExecutable will do this, this
3521 * code must be above it! The original warning from
3522 * tkMacOSXAppInit.c is copied below.
3523 *
3524 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3525 * Tcl interpreter for now. It probably should work to do this
3526 * in the other order, but for now it doesn't seem to.
3527 *
3528 */
3529 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003530#endif
3531
3532
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003533 /* This helps the dynamic loader; in Unicode aware Tcl versions
3534 it also helps Tcl find its encodings. */
3535 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3536 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003537 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003538 if (cexe) {
3539#ifdef MS_WINDOWS
3540 int set_var = 0;
3541 PyObject *str_path;
3542 wchar_t *wcs_path;
3543 DWORD ret;
3544
3545 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3546
3547 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3548 str_path = _get_tcl_lib_path();
3549 if (str_path == NULL && PyErr_Occurred()) {
3550 return NULL;
3551 }
3552 if (str_path != NULL) {
3553 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3554 if (wcs_path == NULL) {
3555 return NULL;
3556 }
3557 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3558 set_var = 1;
3559 }
3560 }
3561
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003562 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003563
3564 if (set_var) {
3565 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3566 PyMem_Free(wcs_path);
3567 }
3568#else
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003569 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003570#endif /* MS_WINDOWS */
3571 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003572 Py_XDECREF(cexe);
3573 Py_DECREF(uexe);
3574 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003576 if (PyErr_Occurred()) {
3577 Py_DECREF(m);
3578 return NULL;
3579 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003580
Guido van Rossum43ff8681998-07-14 18:02:13 +00003581#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003582 /* This was not a good idea; through <Destroy> bindings,
3583 Tcl_Finalize() may invoke Python code but at that point the
3584 interpreter and thread state have already been destroyed! */
3585 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003586#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003587 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003588}