blob: b622c158a48fac0dcd1f94f3cc576454524fb355 [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
Miss Islington (bot)dc191242019-10-04 03:28:54 -070099/* Use OS native encoding for converting between Python strings and
100 Tcl objects.
101 On Windows use UTF-16 (or UTF-32 for 32-bit Tcl_UniChar) with the
102 "surrogatepass" error handler for converting to/from Tcl Unicode objects.
103 On Linux use UTF-8 with the "surrogateescape" error handler for converting
104 to/from Tcl String objects. */
105#ifdef MS_WINDOWS
106#define USE_TCL_UNICODE 1
107#else
108#define USE_TCL_UNICODE 0
109#endif
110
111#if PY_LITTLE_ENDIAN
112#define NATIVE_BYTEORDER -1
113#else
114#define NATIVE_BYTEORDER 1
115#endif
116
Guido van Rossumad4db171998-06-13 13:56:28 +0000117#ifdef MS_WINDOWS
118#include <conio.h>
119#define WAIT_FOR_STDIN
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500120
121static PyObject *
122_get_tcl_lib_path()
123{
124 static PyObject *tcl_library_path = NULL;
125 static int already_checked = 0;
126
127 if (already_checked == 0) {
128 PyObject *prefix;
129 struct stat stat_buf;
130 int stat_return_value;
131
132 prefix = PyUnicode_FromWideChar(Py_GetPrefix(), -1);
133 if (prefix == NULL) {
134 return NULL;
135 }
136
137 /* Check expected location for an installed Python first */
138 tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION);
139 if (tcl_library_path == NULL) {
140 return NULL;
141 }
142 tcl_library_path = PyUnicode_Concat(prefix, tcl_library_path);
143 if (tcl_library_path == NULL) {
144 return NULL;
145 }
146 stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
147 if (stat_return_value == -2) {
148 return NULL;
149 }
150 if (stat_return_value == -1) {
151 /* install location doesn't exist, reset errno and see if
152 we're a repository build */
153 errno = 0;
154#ifdef Py_TCLTK_DIR
155 tcl_library_path = PyUnicode_FromString(
156 Py_TCLTK_DIR "\\lib\\tcl" TCL_VERSION);
157 if (tcl_library_path == NULL) {
158 return NULL;
159 }
160 stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
161 if (stat_return_value == -2) {
162 return NULL;
163 }
164 if (stat_return_value == -1) {
165 /* tcltkDir for a repository build doesn't exist either,
166 reset errno and leave Tcl to its own devices */
167 errno = 0;
168 tcl_library_path = NULL;
169 }
170#else
171 tcl_library_path = NULL;
Guido van Rossumad4db171998-06-13 13:56:28 +0000172#endif
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500173 }
174 already_checked = 1;
175 }
176 return tcl_library_path;
177}
178#endif /* MS_WINDOWS */
Guido van Rossumad4db171998-06-13 13:56:28 +0000179
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000180/* The threading situation is complicated. Tcl is not thread-safe, except
181 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000182
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300183 So we need to use a lock around all uses of Tcl. Previously, the
184 Python interpreter lock was used for this. However, this causes
185 problems when other Python threads need to run while Tcl is blocked
186 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000187
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300188 To solve this problem, a separate lock for Tcl is introduced.
189 Holding it is incompatible with holding Python's interpreter lock.
190 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000191
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300192 ENTER_TCL and LEAVE_TCL are brackets, just like
193 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
194 used whenever a call into Tcl is made that could call an event
195 handler, or otherwise affect the state of a Tcl interpreter. These
196 assume that the surrounding code has the Python interpreter lock;
197 inside the brackets, the Python interpreter lock has been released
198 and the lock for Tcl has been acquired.
199
200 Sometimes, it is necessary to have both the Python lock and the Tcl
201 lock. (For example, when transferring data from the Tcl
202 interpreter result to a Python string object.) This can be done by
203 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
204 reacquires the Python lock (and restores the thread state) but
205 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
206 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000207
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000208 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300209 handlers when the handler needs to use Python. Such event handlers
210 are entered while the lock for Tcl is held; the event handler
211 presumably needs to use Python. ENTER_PYTHON releases the lock for
212 Tcl and acquires the Python interpreter lock, restoring the
213 appropriate thread state, and LEAVE_PYTHON releases the Python
214 interpreter lock and re-acquires the lock for Tcl. It is okay for
215 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
216 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000217
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300218 These locks expand to several statements and brackets; they should
219 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000220
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300221 If Tcl is threaded, this approach won't work anymore. The Tcl
222 interpreter is only valid in the thread that created it, and all Tk
223 activity must happen in this thread, also. That means that the
224 mainloop must be invoked in the thread that created the
225 interpreter. Invoking commands from other threads is possible;
226 _tkinter will queue an event for the interpreter thread, which will
227 then execute the command and pass back the result. If the main
228 thread is not in the mainloop, and invoking commands causes an
229 exception; if the main loop is running but not processing events,
230 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000231
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300232 In addition, for a threaded Tcl, a single global tcl_tstate won't
233 be sufficient anymore, since multiple Tcl interpreters may
234 simultaneously dispatch in different threads. So we use the Tcl TLS
235 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000236
Guido van Rossum00d93061998-05-28 23:06:38 +0000237*/
238
Guido van Rossum65d5b571998-12-21 19:32:43 +0000239static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000240
241#ifdef TCL_THREADS
242static Tcl_ThreadDataKey state_key;
243typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300244#define tcl_tstate \
245 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000246#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000247static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000248#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000249
250#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000251 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
252 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000253
254#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300255 tcl_tstate = NULL; \
256 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000257
Guido van Rossum62320c91998-06-15 04:36:09 +0000258#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000259 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000260
261#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000262 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000263
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000264#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000265 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300266 if(tcl_lock) \
267 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000268
269#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270 { PyThreadState *tstate = PyEval_SaveThread(); \
271 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000272
273#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000274 if (((TkappObject *)self)->threaded && \
275 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300276 PyErr_SetString(PyExc_RuntimeError, \
luzpaza5293b42017-11-05 07:37:50 -0600277 "Calling Tcl from different apartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000278 return 0; \
279 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000280
Guido van Rossum97867b21996-08-08 19:09:53 +0000281#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000282#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000283#endif
284
Guido van Rossum18468821994-06-20 07:49:28 +0000285/**** Tkapp Object Declaration ****/
286
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300287static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000288
Guido van Rossum00d93061998-05-28 23:06:38 +0000289typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000290 PyObject_HEAD
291 Tcl_Interp *interp;
292 int wantobjects;
293 int threaded; /* True if tcl_platform[threaded] */
294 Tcl_ThreadId thread_id;
295 int dispatching;
296 /* We cannot include tclInt.h, as this is internal.
297 So we cache interesting types here. */
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200298 const Tcl_ObjType *OldBooleanType;
Zachary Ware037605b2014-08-05 11:54:34 -0500299 const Tcl_ObjType *BooleanType;
300 const Tcl_ObjType *ByteArrayType;
301 const Tcl_ObjType *DoubleType;
302 const Tcl_ObjType *IntType;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300303 const Tcl_ObjType *WideIntType;
304 const Tcl_ObjType *BignumType;
Zachary Ware037605b2014-08-05 11:54:34 -0500305 const Tcl_ObjType *ListType;
306 const Tcl_ObjType *ProcBodyType;
307 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000308} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000309
Guido van Rossum18468821994-06-20 07:49:28 +0000310#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000311
Guido van Rossum35d43371997-08-02 00:09:09 +0000312#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000313(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000314
Barry Warsawfa701a81997-01-16 00:15:11 +0000315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000316
Guido van Rossum18468821994-06-20 07:49:28 +0000317/**** Error Handling ****/
318
319static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000320static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000321static int errorInCmd = 0;
322static PyObject *excInCmd;
323static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000324static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000325
Guilherme Polob681df42009-02-09 22:33:59 +0000326#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000327static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000328#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000330
Miss Islington (bot)dc191242019-10-04 03:28:54 -0700331static PyObject *Tkapp_UnicodeResult(TkappObject *);
332
Guido van Rossum18468821994-06-20 07:49:28 +0000333static PyObject *
Miss Islington (bot)dc191242019-10-04 03:28:54 -0700334Tkinter_Error(TkappObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +0000335{
Miss Islington (bot)dc191242019-10-04 03:28:54 -0700336 PyObject *res = Tkapp_UnicodeResult(self);
337 if (res != NULL) {
338 PyErr_SetObject(Tkinter_TclError, res);
339 Py_DECREF(res);
340 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000341 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000342}
343
Barry Warsawfa701a81997-01-16 00:15:11 +0000344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000345
Guido van Rossum18468821994-06-20 07:49:28 +0000346/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000347
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000348static int Tkinter_busywaitinterval = 20;
349
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000350#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000351
Guido van Rossum00d93061998-05-28 23:06:38 +0000352/* Millisecond sleep() for Unix platforms. */
353
354static void
Fred Drake509d79a2000-07-08 04:04:38 +0000355Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000356{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000357 /* XXX Too bad if you don't have select(). */
358 struct timeval t;
359 t.tv_sec = milli/1000;
360 t.tv_usec = (milli%1000) * 1000;
361 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000362}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000363#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000364
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000365/* Wait up to 1s for the mainloop to come up. */
366
367static int
368WaitForMainloop(TkappObject* self)
369{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000370 int i;
371 for (i = 0; i < 10; i++) {
372 if (self->dispatching)
373 return 1;
374 Py_BEGIN_ALLOW_THREADS
375 Sleep(100);
376 Py_END_ALLOW_THREADS
377 }
378 if (self->dispatching)
379 return 1;
380 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
381 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000382}
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000384
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000385
Guido van Rossum18468821994-06-20 07:49:28 +0000386#define ARGSZ 64
387
Barry Warsawfa701a81997-01-16 00:15:11 +0000388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000389
Guido van Rossum18468821994-06-20 07:49:28 +0000390static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200391unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
392{
393 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
Miss Islington (bot)dc191242019-10-04 03:28:54 -0700394 if (r != NULL || !PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
395 return r;
396 }
397
398 char *buf = NULL;
399 PyErr_Clear();
400 /* Tcl encodes null character as \xc0\x80 */
401 if (memchr(s, '\xc0', size)) {
402 char *q;
403 const char *e = s + size;
404 q = buf = (char *)PyMem_Malloc(size);
405 if (buf == NULL) {
406 PyErr_NoMemory();
407 return NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200408 }
Miss Islington (bot)dc191242019-10-04 03:28:54 -0700409 while (s != e) {
410 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
411 *q++ = '\0';
412 s += 2;
413 }
414 else
415 *q++ = *s++;
416 }
417 s = buf;
418 size = q - s;
419 }
420 r = PyUnicode_DecodeUTF8(s, size, "surrogateescape");
421 if (buf != NULL) {
422 PyMem_Free(buf);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200423 }
424 return r;
425}
426
427static PyObject *
428unicodeFromTclString(const char *s)
429{
430 return unicodeFromTclStringAndSize(s, strlen(s));
431}
432
433static PyObject *
434unicodeFromTclObj(Tcl_Obj *value)
435{
436 int len;
Miss Islington (bot)dc191242019-10-04 03:28:54 -0700437#if USE_TCL_UNICODE
438 int byteorder = NATIVE_BYTEORDER;
439 const Tcl_UniChar *u = Tcl_GetUnicodeFromObj(value, &len);
440 if (sizeof(Tcl_UniChar) == 2)
441 return PyUnicode_DecodeUTF16((const char *)u, len * 2,
442 "surrogatepass", &byteorder);
443 else if (sizeof(Tcl_UniChar) == 4)
444 return PyUnicode_DecodeUTF32((const char *)u, len * 4,
445 "surrogatepass", &byteorder);
446 else
447 Py_UNREACHABLE();
448#else
449 const char *s = Tcl_GetStringFromObj(value, &len);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200450 return unicodeFromTclStringAndSize(s, len);
Miss Islington (bot)dc191242019-10-04 03:28:54 -0700451#endif
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200452}
453
454
455static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300456Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000457{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000458 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300459 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000460 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000462 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300463 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000464 }
Guido van Rossum18468821994-06-20 07:49:28 +0000465
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
467 /* Not a list.
468 * Could be a quoted string containing funnies, e.g. {"}.
469 * Return the string itself.
470 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200471 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000472 }
Guido van Rossum18468821994-06-20 07:49:28 +0000473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000474 if (argc == 0)
475 v = PyUnicode_FromString("");
476 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200477 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000478 else if ((v = PyTuple_New(argc)) != NULL) {
479 int i;
480 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000481
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000482 for (i = 0; i < argc; i++) {
483 if ((w = Split(argv[i])) == NULL) {
484 Py_DECREF(v);
485 v = NULL;
486 break;
487 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300488 PyTuple_SET_ITEM(v, i, w);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000489 }
490 }
491 Tcl_Free(FREECAST argv);
492 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000493}
494
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300495/* In some cases, Tcl will still return strings that are supposed to
496 be lists. SplitObj walks through a nested tuple, finding string
497 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000498
Martin v. Löwis59683e82008-06-13 07:50:45 +0000499static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000500SplitObj(PyObject *arg)
501{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000502 if (PyTuple_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200503 Py_ssize_t i, size;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000504 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000505
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300506 size = PyTuple_GET_SIZE(arg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000507 result = NULL;
508 /* Recursively invoke SplitObj for all tuple items.
509 If this does not return a new object, no action is
510 needed. */
511 for(i = 0; i < size; i++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300512 elem = PyTuple_GET_ITEM(arg, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513 newelem = SplitObj(elem);
514 if (!newelem) {
515 Py_XDECREF(result);
516 return NULL;
517 }
518 if (!result) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200519 Py_ssize_t k;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000520 if (newelem == elem) {
521 Py_DECREF(newelem);
522 continue;
523 }
524 result = PyTuple_New(size);
525 if (!result)
526 return NULL;
527 for(k = 0; k < i; k++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300528 elem = PyTuple_GET_ITEM(arg, k);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000529 Py_INCREF(elem);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300530 PyTuple_SET_ITEM(result, k, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000531 }
532 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300533 PyTuple_SET_ITEM(result, i, newelem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000534 }
535 if (result)
536 return result;
537 /* Fall through, returning arg. */
538 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300539 else if (PyList_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200540 Py_ssize_t i, size;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300541 PyObject *elem, *newelem, *result;
542
543 size = PyList_GET_SIZE(arg);
544 result = PyTuple_New(size);
545 if (!result)
546 return NULL;
547 /* Recursively invoke SplitObj for all list items. */
548 for(i = 0; i < size; i++) {
549 elem = PyList_GET_ITEM(arg, i);
550 newelem = SplitObj(elem);
551 if (!newelem) {
552 Py_XDECREF(result);
553 return NULL;
554 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300555 PyTuple_SET_ITEM(result, i, newelem);
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300556 }
557 return result;
558 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300559 else if (PyUnicode_Check(arg)) {
560 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300561 const char **argv;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200562 const char *list = PyUnicode_AsUTF8(arg);
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300563
564 if (list == NULL ||
565 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
566 Py_INCREF(arg);
567 return arg;
568 }
569 Tcl_Free(FREECAST argv);
570 if (argc > 1)
571 return Split(list);
572 /* Fall through, returning arg. */
573 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000574 else if (PyBytes_Check(arg)) {
575 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300576 const char **argv;
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300577 char *list = PyBytes_AS_STRING(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000579 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
580 Py_INCREF(arg);
581 return arg;
582 }
583 Tcl_Free(FREECAST argv);
584 if (argc > 1)
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300585 return Split(PyBytes_AS_STRING(arg));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 /* Fall through, returning arg. */
587 }
588 Py_INCREF(arg);
589 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000590}
Barry Warsawfa701a81997-01-16 00:15:11 +0000591
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000592
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +0300593/*[clinic input]
594module _tkinter
595class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec"
596class _tkinter.Tcl_Obj "PyTclObject *" "&PyTclObject_Type_spec"
597class _tkinter.tktimertoken "TkttObject *" "&Tktt_Type_spec"
598[clinic start generated code]*/
599/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b1ebf15c162ee229]*/
600
Guido van Rossum18468821994-06-20 07:49:28 +0000601/**** Tkapp Object ****/
602
603#ifndef WITH_APPINIT
604int
Fred Drake509d79a2000-07-08 04:04:38 +0000605Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000606{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000608
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 if (Tcl_Init(interp) == TCL_ERROR) {
610 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
611 return TCL_ERROR;
612 }
Guilherme Polob681df42009-02-09 22:33:59 +0000613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 _tkinter_skip_tk_init = Tcl_GetVar(interp,
615 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
616 if (_tkinter_skip_tk_init != NULL &&
617 strcmp(_tkinter_skip_tk_init, "1") == 0) {
618 return TCL_OK;
619 }
Guilherme Polob681df42009-02-09 22:33:59 +0000620
621#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000622 if (tk_load_failed) {
623 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
624 return TCL_ERROR;
625 }
Guilherme Polob681df42009-02-09 22:33:59 +0000626#endif
627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000628 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000629#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000631#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
633 return TCL_ERROR;
634 }
Guilherme Polob681df42009-02-09 22:33:59 +0000635
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000637}
638#endif /* !WITH_APPINIT */
639
Guido van Rossum18468821994-06-20 07:49:28 +0000640
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641
Barry Warsawfa701a81997-01-16 00:15:11 +0000642
643/* Initialize the Tk application; see the `main' function in
644 * `tkMain.c'.
645 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000646
Thomas Wouters58d05102000-07-24 14:43:35 +0000647static void EnableEventHook(void); /* Forward */
648static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000649
Barry Warsawfa701a81997-01-16 00:15:11 +0000650static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300651Tkapp_New(const char *screenName, const char *className,
652 int interactive, int wantobjects, int wantTk, int sync,
653 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000654{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000655 TkappObject *v;
656 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000657
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300658 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000659 if (v == NULL)
660 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000661
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 v->interp = Tcl_CreateInterp();
663 v->wantobjects = wantobjects;
664 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
665 TCL_GLOBAL_ONLY) != NULL;
666 v->thread_id = Tcl_GetCurrentThread();
667 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000668
669#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000670 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300671 PyErr_SetString(PyExc_RuntimeError,
672 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000673 Py_DECREF(v);
674 return 0;
675 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000676#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 if (v->threaded && tcl_lock) {
678 /* If Tcl is threaded, we don't need the lock. */
679 PyThread_free_lock(tcl_lock);
680 tcl_lock = NULL;
681 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000682
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200683 v->OldBooleanType = Tcl_GetObjType("boolean");
684 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 v->ByteArrayType = Tcl_GetObjType("bytearray");
686 v->DoubleType = Tcl_GetObjType("double");
687 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300688 v->WideIntType = Tcl_GetObjType("wideInt");
689 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 v->ListType = Tcl_GetObjType("list");
691 v->ProcBodyType = Tcl_GetObjType("procbody");
692 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 /* Delete the 'exit' command, which can screw things up */
695 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000696
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000697 if (screenName != NULL)
698 Tcl_SetVar2(v->interp, "env", "DISPLAY",
699 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000700
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 if (interactive)
702 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
703 else
704 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000705
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200707 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000708 if (!argv0) {
709 PyErr_NoMemory();
710 Py_DECREF(v);
711 return NULL;
712 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000713
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000714 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200715 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
716 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200718 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000719
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 if (! wantTk) {
721 Tcl_SetVar(v->interp,
722 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
723 }
Guilherme Polob681df42009-02-09 22:33:59 +0000724#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000725 else if (tk_load_failed) {
726 Tcl_SetVar(v->interp,
727 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
728 }
Guilherme Polob681df42009-02-09 22:33:59 +0000729#endif
David Aschere2b4b322004-02-18 05:59:53 +0000730
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000731 /* some initial arguments need to be in argv */
732 if (sync || use) {
733 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200734 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000735
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000736 if (sync)
737 len += sizeof "-sync";
738 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200739 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000740
Victor Stinneree6c3c72014-09-11 17:50:21 +0200741 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 if (!args) {
743 PyErr_NoMemory();
744 Py_DECREF(v);
745 return NULL;
746 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000747
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000748 args[0] = '\0';
749 if (sync)
750 strcat(args, "-sync");
751 if (use) {
752 if (sync)
753 strcat(args, " ");
754 strcat(args, "-use ");
755 strcat(args, use);
756 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000757
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000758 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200759 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000760 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000761
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500762#ifdef MS_WINDOWS
763 {
764 PyObject *str_path;
765 PyObject *utf8_path;
766 DWORD ret;
767
768 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
769 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
770 str_path = _get_tcl_lib_path();
771 if (str_path == NULL && PyErr_Occurred()) {
772 return NULL;
773 }
774 if (str_path != NULL) {
775 utf8_path = PyUnicode_AsUTF8String(str_path);
776 if (utf8_path == NULL) {
777 return NULL;
778 }
779 Tcl_SetVar(v->interp,
780 "tcl_library",
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300781 PyBytes_AS_STRING(utf8_path),
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500782 TCL_GLOBAL_ONLY);
783 Py_DECREF(utf8_path);
784 }
785 }
786 }
787#endif
788
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000789 if (Tcl_AppInit(v->interp) != TCL_OK) {
Miss Islington (bot)dc191242019-10-04 03:28:54 -0700790 PyObject *result = Tkinter_Error(v);
Guilherme Polob681df42009-02-09 22:33:59 +0000791#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000792 if (wantTk) {
793 const char *_tkinter_tk_failed;
794 _tkinter_tk_failed = Tcl_GetVar(v->interp,
795 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000796
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000797 if ( _tkinter_tk_failed != NULL &&
798 strcmp(_tkinter_tk_failed, "1") == 0) {
799 tk_load_failed = 1;
800 }
801 }
Guilherme Polob681df42009-02-09 22:33:59 +0000802#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000803 Py_DECREF((PyObject *)v);
804 return (TkappObject *)result;
805 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000806
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000807 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000808
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000809 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000810}
811
Barry Warsawfa701a81997-01-16 00:15:11 +0000812
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000813static void
814Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000815 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000816{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000817 Py_BEGIN_ALLOW_THREADS;
818 Tcl_MutexLock(mutex);
819 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
820 Tcl_ThreadAlert(self->thread_id);
821 Tcl_ConditionWait(cond, mutex, NULL);
822 Tcl_MutexUnlock(mutex);
823 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000824}
825
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000826
Guido van Rossum18468821994-06-20 07:49:28 +0000827/** Tcl Eval **/
828
Martin v. Löwisffad6332002-11-26 09:28:05 +0000829typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000830 PyObject_HEAD
831 Tcl_Obj *value;
832 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000833} PyTclObject;
834
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300835static PyObject *PyTclObject_Type;
836#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000837
838static PyObject *
839newPyTclObject(Tcl_Obj *arg)
840{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000841 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300842 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000843 if (self == NULL)
844 return NULL;
845 Tcl_IncrRefCount(arg);
846 self->value = arg;
847 self->string = NULL;
848 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000849}
850
851static void
852PyTclObject_dealloc(PyTclObject *self)
853{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200854 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000855 Tcl_DecrRefCount(self->value);
856 Py_XDECREF(self->string);
857 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200858 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000859}
860
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000861/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000862PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000863"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000864
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000865static PyObject *
866PyTclObject_string(PyTclObject *self, void *ignored)
867{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000868 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200869 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000870 if (!self->string)
871 return NULL;
872 }
873 Py_INCREF(self->string);
874 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000875}
876
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000877static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200878PyTclObject_str(PyTclObject *self)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000879{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200880 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 Py_INCREF(self->string);
882 return self->string;
883 }
884 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200885 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000886}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000887
Martin v. Löwisffad6332002-11-26 09:28:05 +0000888static PyObject *
889PyTclObject_repr(PyTclObject *self)
890{
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200891 PyObject *repr, *str = PyTclObject_str(self);
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300892 if (str == NULL)
893 return NULL;
894 repr = PyUnicode_FromFormat("<%s object: %R>",
895 self->value->typePtr->name, str);
896 Py_DECREF(str);
897 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000898}
899
Mark Dickinson211c6252009-02-01 10:28:51 +0000900static PyObject *
901PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000902{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000903 int result;
Mark Dickinson211c6252009-02-01 10:28:51 +0000904
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000905 /* neither argument should be NULL, unless something's gone wrong */
906 if (self == NULL || other == NULL) {
907 PyErr_BadInternalCall();
908 return NULL;
909 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000910
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000911 /* both arguments should be instances of PyTclObject */
912 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
stratakise8b19652017-11-02 11:32:54 +0100913 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000914 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000915
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000916 if (self == other)
917 /* fast path when self and other are identical */
918 result = 0;
919 else
920 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
921 Tcl_GetString(((PyTclObject *)other)->value));
stratakise8b19652017-11-02 11:32:54 +0100922 Py_RETURN_RICHCOMPARE(result, 0, op);
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000923}
924
Martin v. Löwis39195712003-01-04 00:33:13 +0000925PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
926
Martin v. Löwisffad6332002-11-26 09:28:05 +0000927static PyObject*
928get_typename(PyTclObject* obj, void* ignored)
929{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200930 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000931}
932
Martin v. Löwis39195712003-01-04 00:33:13 +0000933
Martin v. Löwisffad6332002-11-26 09:28:05 +0000934static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000935 {"typename", (getter)get_typename, NULL, get_typename__doc__},
936 {"string", (getter)PyTclObject_string, NULL,
937 PyTclObject_string__doc__},
938 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000939};
940
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300941static PyType_Slot PyTclObject_Type_slots[] = {
942 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
943 {Py_tp_repr, (reprfunc)PyTclObject_repr},
944 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200945 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300946 {Py_tp_richcompare, PyTclObject_richcompare},
947 {Py_tp_getset, PyTclObject_getsetlist},
948 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000949};
950
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300951static PyType_Spec PyTclObject_Type_spec = {
952 "_tkinter.Tcl_Obj",
953 sizeof(PyTclObject),
954 0,
955 Py_TPFLAGS_DEFAULT,
956 PyTclObject_Type_slots,
957};
958
959
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700960#if SIZE_MAX > INT_MAX
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300961#define CHECK_STRING_LENGTH(s) do { \
962 if (s != NULL && strlen(s) >= INT_MAX) { \
963 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
964 return NULL; \
965 } } while(0)
966#else
967#define CHECK_STRING_LENGTH(s)
968#endif
969
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300970#ifdef HAVE_LIBTOMMAMTH
971static Tcl_Obj*
972asBignumObj(PyObject *value)
973{
974 Tcl_Obj *result;
975 int neg;
976 PyObject *hexstr;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200977 const char *hexchars;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300978 mp_int bigValue;
979
980 neg = Py_SIZE(value) < 0;
981 hexstr = _PyLong_Format(value, 16);
982 if (hexstr == NULL)
983 return NULL;
984 hexchars = PyUnicode_AsUTF8(hexstr);
985 if (hexchars == NULL) {
986 Py_DECREF(hexstr);
987 return NULL;
988 }
989 hexchars += neg + 2; /* skip sign and "0x" */
990 mp_init(&bigValue);
991 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
992 mp_clear(&bigValue);
993 Py_DECREF(hexstr);
994 PyErr_NoMemory();
995 return NULL;
996 }
997 Py_DECREF(hexstr);
998 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
999 result = Tcl_NewBignumObj(&bigValue);
1000 mp_clear(&bigValue);
1001 if (result == NULL) {
1002 PyErr_NoMemory();
1003 return NULL;
1004 }
1005 return result;
1006}
1007#endif
1008
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001009static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001010AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001011{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001012 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001013
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001014 if (PyBytes_Check(value)) {
1015 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
1016 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1017 return NULL;
1018 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +03001019 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001020 (int)PyBytes_GET_SIZE(value));
1021 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001022
1023 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001024 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001025
1026 if (PyLong_CheckExact(value)) {
1027 int overflow;
1028 long longValue;
1029#ifdef TCL_WIDE_INT_TYPE
1030 Tcl_WideInt wideValue;
1031#endif
1032 longValue = PyLong_AsLongAndOverflow(value, &overflow);
1033 if (!overflow) {
1034 return Tcl_NewLongObj(longValue);
1035 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001036 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001037 fall through to wideInt handling. */
1038#ifdef TCL_WIDE_INT_TYPE
1039 if (_PyLong_AsByteArray((PyLongObject *)value,
1040 (unsigned char *)(void *)&wideValue,
1041 sizeof(wideValue),
1042 PY_LITTLE_ENDIAN,
1043 /* signed */ 1) == 0) {
1044 return Tcl_NewWideIntObj(wideValue);
1045 }
1046 PyErr_Clear();
1047#endif
1048 /* If there is an overflow in the wideInt conversion,
1049 fall through to bignum handling. */
1050#ifdef HAVE_LIBTOMMAMTH
1051 return asBignumObj(value);
1052#endif
1053 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001054 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001056
1057 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001058 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001059
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +03001060 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001061 Tcl_Obj **argv;
1062 Py_ssize_t size, i;
1063
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001064 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001065 if (size == 0)
1066 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001067 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001068 PyErr_SetString(PyExc_OverflowError,
1069 PyTuple_Check(value) ? "tuple is too long" :
1070 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001071 return NULL;
1072 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001073 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
1074 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001075 PyErr_NoMemory();
1076 return NULL;
1077 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001078 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001079 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001080 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001081 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001082 return result;
1083 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001084
1085 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001086 if (PyUnicode_READY(value) == -1)
1087 return NULL;
1088
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001089 Py_ssize_t size = PyUnicode_GET_LENGTH(value);
1090 if (size == 0) {
1091 return Tcl_NewStringObj("", 0);
1092 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001093 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1094 PyErr_SetString(PyExc_OverflowError, "string is too long");
1095 return NULL;
1096 }
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001097 if (PyUnicode_IS_ASCII(value)) {
1098 return Tcl_NewStringObj((const char *)PyUnicode_DATA(value),
1099 (int)size);
1100 }
1101
1102 PyObject *encoded;
1103#if USE_TCL_UNICODE
1104 if (sizeof(Tcl_UniChar) == 2)
1105 encoded = _PyUnicode_EncodeUTF16(value,
1106 "surrogatepass", NATIVE_BYTEORDER);
1107 else if (sizeof(Tcl_UniChar) == 4)
1108 encoded = _PyUnicode_EncodeUTF32(value,
1109 "surrogatepass", NATIVE_BYTEORDER);
1110 else
1111 Py_UNREACHABLE();
1112#else
1113 encoded = _PyUnicode_AsUTF8String(value, "surrogateescape");
1114#endif
1115 if (!encoded) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001116 return NULL;
1117 }
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001118 size = PyBytes_GET_SIZE(encoded);
1119 if (size > INT_MAX) {
1120 Py_DECREF(encoded);
1121 PyErr_SetString(PyExc_OverflowError, "string is too long");
1122 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001123 }
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001124#if USE_TCL_UNICODE
1125 result = Tcl_NewUnicodeObj((const Tcl_UniChar *)PyBytes_AS_STRING(encoded),
1126 (int)(size / sizeof(Tcl_UniChar)));
1127#else
1128 result = Tcl_NewStringObj(PyBytes_AS_STRING(encoded), (int)size);
1129#endif
1130 Py_DECREF(encoded);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001131 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001132 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001133
1134 if (PyTclObject_Check(value)) {
Serhiy Storchakadf13df42018-10-23 22:40:54 +03001135 return ((PyTclObject*)value)->value;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001136 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001137
1138 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001139 PyObject *v = PyObject_Str(value);
1140 if (!v)
1141 return 0;
1142 result = AsObj(v);
1143 Py_DECREF(v);
1144 return result;
1145 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001146}
1147
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001148static PyObject *
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001149fromBoolean(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001150{
1151 int boolValue;
1152 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1153 return Tkinter_Error(tkapp);
1154 return PyBool_FromLong(boolValue);
1155}
1156
Martin v. Löwisffad6332002-11-26 09:28:05 +00001157static PyObject*
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001158fromWideIntObj(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001159{
1160 Tcl_WideInt wideValue;
1161 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001162 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1163 return PyLong_FromLongLong(wideValue);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001164 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1165 sizeof(wideValue),
1166 PY_LITTLE_ENDIAN,
1167 /* signed */ 1);
1168 }
1169 return NULL;
1170}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001171
1172#ifdef HAVE_LIBTOMMAMTH
1173static PyObject*
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001174fromBignumObj(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001175{
1176 mp_int bigValue;
1177 unsigned long numBytes;
1178 unsigned char *bytes;
1179 PyObject *res;
1180
1181 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1182 return Tkinter_Error(tkapp);
1183 numBytes = mp_unsigned_bin_size(&bigValue);
1184 bytes = PyMem_Malloc(numBytes);
1185 if (bytes == NULL) {
1186 mp_clear(&bigValue);
1187 return PyErr_NoMemory();
1188 }
1189 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1190 &numBytes) != MP_OKAY) {
1191 mp_clear(&bigValue);
1192 PyMem_Free(bytes);
1193 return PyErr_NoMemory();
1194 }
1195 res = _PyLong_FromByteArray(bytes, numBytes,
1196 /* big-endian */ 0,
1197 /* unsigned */ 0);
1198 PyMem_Free(bytes);
1199 if (res != NULL && bigValue.sign == MP_NEG) {
1200 PyObject *res2 = PyNumber_Negative(res);
1201 Py_DECREF(res);
1202 res = res2;
1203 }
1204 mp_clear(&bigValue);
1205 return res;
1206}
1207#endif
1208
Martin v. Löwisffad6332002-11-26 09:28:05 +00001209static PyObject*
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001210FromObj(TkappObject *tkapp, Tcl_Obj *value)
Martin v. Löwisffad6332002-11-26 09:28:05 +00001211{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001212 PyObject *result = NULL;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001213 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001214
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001215 if (value->typePtr == NULL) {
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001216 return unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001217 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001218
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001219 if (value->typePtr == tkapp->BooleanType ||
1220 value->typePtr == tkapp->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001221 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001222 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001223
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001224 if (value->typePtr == tkapp->ByteArrayType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001225 int size;
1226 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1227 return PyBytes_FromStringAndSize(data, size);
1228 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001229
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001230 if (value->typePtr == tkapp->DoubleType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001231 return PyFloat_FromDouble(value->internalRep.doubleValue);
1232 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001233
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001234 if (value->typePtr == tkapp->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001235 long longValue;
1236 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1237 return PyLong_FromLong(longValue);
1238 /* If there is an error in the long conversion,
1239 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001240 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001241
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001242 if (value->typePtr == tkapp->IntType ||
1243 value->typePtr == tkapp->WideIntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001244 result = fromWideIntObj(tkapp, value);
1245 if (result != NULL || PyErr_Occurred())
1246 return result;
1247 Tcl_ResetResult(interp);
1248 /* If there is an error in the wideInt conversion,
1249 fall through to bignum handling. */
1250 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001251
1252#ifdef HAVE_LIBTOMMAMTH
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001253 if (value->typePtr == tkapp->IntType ||
1254 value->typePtr == tkapp->WideIntType ||
1255 value->typePtr == tkapp->BignumType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001256 return fromBignumObj(tkapp, value);
1257 }
1258#endif
1259
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001260 if (value->typePtr == tkapp->ListType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001261 int size;
1262 int i, status;
1263 PyObject *elem;
1264 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001265
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001266 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001267 if (status == TCL_ERROR)
1268 return Tkinter_Error(tkapp);
1269 result = PyTuple_New(size);
1270 if (!result)
1271 return NULL;
1272 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001273 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001274 if (status == TCL_ERROR) {
1275 Py_DECREF(result);
1276 return Tkinter_Error(tkapp);
1277 }
1278 elem = FromObj(tkapp, tcl_elem);
1279 if (!elem) {
1280 Py_DECREF(result);
1281 return NULL;
1282 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001283 PyTuple_SET_ITEM(result, i, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 }
1285 return result;
1286 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001287
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001288 if (value->typePtr == tkapp->ProcBodyType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001289 /* fall through: return tcl object. */
1290 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001291
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001292 if (value->typePtr == tkapp->StringType) {
1293 return unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001294 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001295
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001296#if TK_HEX_VERSION >= 0x08050000
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001297 if (tkapp->BooleanType == NULL &&
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001298 strcmp(value->typePtr->name, "booleanString") == 0) {
1299 /* booleanString type is not registered in Tcl */
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001300 tkapp->BooleanType = value->typePtr;
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001301 return fromBoolean(tkapp, value);
1302 }
1303#endif
1304
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001305#ifdef HAVE_LIBTOMMAMTH
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001306 if (tkapp->BignumType == NULL &&
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001307 strcmp(value->typePtr->name, "bignum") == 0) {
1308 /* bignum type is not registered in Tcl */
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001309 tkapp->BignumType = value->typePtr;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001310 return fromBignumObj(tkapp, value);
1311 }
1312#endif
1313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001314 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001315}
1316
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001317/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001318TCL_DECLARE_MUTEX(call_mutex)
1319
1320typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001321 Tcl_Event ev; /* Must be first */
1322 TkappObject *self;
1323 PyObject *args;
1324 int flags;
1325 PyObject **res;
1326 PyObject **exc_type, **exc_value, **exc_tb;
1327 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001328} Tkapp_CallEvent;
1329
1330void
1331Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001332{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001333 int i;
1334 for (i = 0; i < objc; i++)
1335 Tcl_DecrRefCount(objv[i]);
1336 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001337 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001338}
Guido van Rossum18468821994-06-20 07:49:28 +00001339
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001340/* Convert Python objects to Tcl objects. This must happen in the
1341 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001342
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001343static Tcl_Obj**
1344Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1345{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001347 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001348 if (args == NULL)
1349 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001350
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001351 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 objv[0] = AsObj(args);
Serhiy Storchaka0b3ec192017-03-23 17:53:47 +02001353 if (objv[0] == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001354 goto finally;
1355 objc = 1;
1356 Tcl_IncrRefCount(objv[0]);
1357 }
1358 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001359 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001361 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001362 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001363 PyErr_SetString(PyExc_OverflowError,
1364 PyTuple_Check(args) ? "tuple is too long" :
1365 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001366 return NULL;
1367 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001368 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001369 if (objv == NULL) {
1370 PyErr_NoMemory();
1371 objc = 0;
1372 goto finally;
1373 }
1374 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001376 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001377 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001378 if (v == Py_None) {
1379 objc = i;
1380 break;
1381 }
1382 objv[i] = AsObj(v);
1383 if (!objv[i]) {
1384 /* Reset objc, so it attempts to clear
1385 objects only up to i. */
1386 objc = i;
1387 goto finally;
1388 }
1389 Tcl_IncrRefCount(objv[i]);
1390 }
1391 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001392 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001393 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001394finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001395 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001396 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001397}
Guido van Rossum212643f1998-04-29 16:22:14 +00001398
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001399/* Convert the results of a command call into a Python string. */
1400
1401static PyObject *
1402Tkapp_UnicodeResult(TkappObject *self)
1403{
1404 return unicodeFromTclObj(Tcl_GetObjResult(self->interp));
1405}
1406
1407
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001408/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001409
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001410static PyObject *
1411Tkapp_ObjectResult(TkappObject *self)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001412{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001413 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001414 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001415 if (self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001416 /* Not sure whether the IncrRef is necessary, but something
1417 may overwrite the interpreter result while we are
1418 converting it. */
1419 Tcl_IncrRefCount(value);
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001420 res = FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001421 Tcl_DecrRefCount(value);
1422 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001423 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001424 }
1425 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001426}
Guido van Rossum632de272000-03-29 00:19:50 +00001427
Benjamin Peterson5879d412009-03-30 14:51:56 +00001428
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001429/* Tkapp_CallProc is the event procedure that is executed in the context of
1430 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1431 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001432
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001433static int
1434Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1435{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001436 Tcl_Obj *objStore[ARGSZ];
1437 Tcl_Obj **objv;
1438 int objc;
1439 int i;
1440 ENTER_PYTHON
1441 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1442 if (!objv) {
1443 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1444 *(e->res) = NULL;
1445 }
1446 LEAVE_PYTHON
1447 if (!objv)
1448 goto done;
1449 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1450 ENTER_PYTHON
1451 if (i == TCL_ERROR) {
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001452 *(e->res) = Tkinter_Error(e->self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001453 }
1454 else {
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001455 *(e->res) = Tkapp_ObjectResult(e->self);
1456 }
1457 if (*(e->res) == NULL) {
1458 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001459 }
1460 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001462 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001463done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001464 /* Wake up calling thread. */
1465 Tcl_MutexLock(&call_mutex);
1466 Tcl_ConditionNotify(e->done);
1467 Tcl_MutexUnlock(&call_mutex);
1468 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001469}
1470
Benjamin Peterson5879d412009-03-30 14:51:56 +00001471
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001472/* This is the main entry point for calling a Tcl command.
1473 It supports three cases, with regard to threading:
1474 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1475 the context of the calling thread.
1476 2. Tcl is threaded, caller of the command is in the interpreter thread:
1477 Execute the command in the calling thread. Since the Tcl lock will
1478 not be used, we can merge that with case 1.
1479 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1480 the interpreter thread. Allocation of Tcl objects needs to occur in the
1481 interpreter thread, so we ship the PyObject* args to the target thread,
1482 and perform processing there. */
1483
1484static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001485Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001487 Tcl_Obj *objStore[ARGSZ];
1488 Tcl_Obj **objv = NULL;
1489 int objc, i;
1490 PyObject *res = NULL;
1491 TkappObject *self = (TkappObject*)selfptr;
1492 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001494 /* If args is a single tuple, replace with contents of tuple */
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001495 if (PyTuple_GET_SIZE(args) == 1) {
1496 PyObject *item = PyTuple_GET_ITEM(args, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001497 if (PyTuple_Check(item))
1498 args = item;
1499 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001500 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1501 /* We cannot call the command directly. Instead, we must
1502 marshal the parameters to the interpreter thread. */
1503 Tkapp_CallEvent *ev;
1504 Tcl_Condition cond = NULL;
1505 PyObject *exc_type, *exc_value, *exc_tb;
1506 if (!WaitForMainloop(self))
1507 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001508 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1509 if (ev == NULL) {
1510 PyErr_NoMemory();
1511 return NULL;
1512 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001513 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1514 ev->self = self;
1515 ev->args = args;
1516 ev->res = &res;
1517 ev->exc_type = &exc_type;
1518 ev->exc_value = &exc_value;
1519 ev->exc_tb = &exc_tb;
1520 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001521
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001522 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001524 if (res == NULL) {
1525 if (exc_type)
1526 PyErr_Restore(exc_type, exc_value, exc_tb);
1527 else
1528 PyErr_SetObject(Tkinter_TclError, exc_value);
1529 }
1530 Tcl_ConditionFinalize(&cond);
1531 }
1532 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001534
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001535 objv = Tkapp_CallArgs(args, objStore, &objc);
1536 if (!objv)
1537 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001539 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001542
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001543 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001544
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001545 if (i == TCL_ERROR)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001546 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 else
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001548 res = Tkapp_ObjectResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001549
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001551
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001552 Tkapp_CallDeallocArgs(objv, objStore, objc);
1553 }
1554 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001555}
1556
1557
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001558/*[clinic input]
1559_tkinter.tkapp.eval
1560
1561 script: str
1562 /
1563
1564[clinic start generated code]*/
1565
Barry Warsawfa701a81997-01-16 00:15:11 +00001566static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001567_tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1568/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001569{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001570 PyObject *res = NULL;
1571 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001572
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001573 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001574 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001576 ENTER_TCL
1577 err = Tcl_Eval(Tkapp_Interp(self), script);
1578 ENTER_OVERLAP
1579 if (err == TCL_ERROR)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001580 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001581 else
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001582 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001583 LEAVE_OVERLAP_TCL
1584 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001585}
1586
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001587/*[clinic input]
1588_tkinter.tkapp.evalfile
1589
1590 fileName: str
1591 /
1592
1593[clinic start generated code]*/
1594
Guido van Rossum18468821994-06-20 07:49:28 +00001595static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001596_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1597/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001598{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001599 PyObject *res = NULL;
1600 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001601
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001602 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001603 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001605 ENTER_TCL
1606 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1607 ENTER_OVERLAP
1608 if (err == TCL_ERROR)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001609 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001610 else
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001611 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001612 LEAVE_OVERLAP_TCL
1613 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001614}
1615
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001616/*[clinic input]
1617_tkinter.tkapp.record
1618
1619 script: str
1620 /
1621
1622[clinic start generated code]*/
1623
Guido van Rossum18468821994-06-20 07:49:28 +00001624static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001625_tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1626/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001627{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001628 PyObject *res = NULL;
1629 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001630
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001631 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001632 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001634 ENTER_TCL
1635 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1636 ENTER_OVERLAP
1637 if (err == TCL_ERROR)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001638 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001639 else
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001640 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001641 LEAVE_OVERLAP_TCL
1642 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001643}
1644
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001645/*[clinic input]
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001646_tkinter.tkapp.adderrorinfo
Guido van Rossum18468821994-06-20 07:49:28 +00001647
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001648 msg: str
1649 /
1650
1651[clinic start generated code]*/
1652
1653static PyObject *
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001654_tkinter_tkapp_adderrorinfo_impl(TkappObject *self, const char *msg)
1655/*[clinic end generated code: output=52162eaca2ee53cb input=f4b37aec7c7e8c77]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001656{
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001657 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001658 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001659
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001660 ENTER_TCL
1661 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1662 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001663
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001664 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001665}
1666
Barry Warsawfa701a81997-01-16 00:15:11 +00001667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001668
Guido van Rossum18468821994-06-20 07:49:28 +00001669/** Tcl Variable **/
1670
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001671typedef PyObject* (*EventFunc)(TkappObject *, PyObject *, int);
Benjamin Peterson5879d412009-03-30 14:51:56 +00001672
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001673TCL_DECLARE_MUTEX(var_mutex)
1674
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001675typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001676 Tcl_Event ev; /* must be first */
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001677 TkappObject *self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001678 PyObject *args;
1679 int flags;
1680 EventFunc func;
1681 PyObject **res;
1682 PyObject **exc_type;
1683 PyObject **exc_val;
1684 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001685} VarEvent;
1686
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001687/*[python]
1688
1689class varname_converter(CConverter):
1690 type = 'const char *'
1691 converter = 'varname_converter'
1692
1693[python]*/
1694/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1695
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001696static int
1697varname_converter(PyObject *in, void *_out)
1698{
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +02001699 const char *s;
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001700 const char **out = (const char**)_out;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001701 if (PyBytes_Check(in)) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001702 if (PyBytes_GET_SIZE(in) > INT_MAX) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001703 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1704 return 0;
1705 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001706 s = PyBytes_AS_STRING(in);
1707 if (strlen(s) != (size_t)PyBytes_GET_SIZE(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001708 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001709 return 0;
1710 }
1711 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001712 return 1;
1713 }
1714 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001715 Py_ssize_t size;
1716 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001717 if (s == NULL) {
1718 return 0;
1719 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001720 if (size > INT_MAX) {
1721 PyErr_SetString(PyExc_OverflowError, "string is too long");
1722 return 0;
1723 }
Victor Stinner706768c2014-08-16 01:03:39 +02001724 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001725 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001726 return 0;
1727 }
1728 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001729 return 1;
1730 }
1731 if (PyTclObject_Check(in)) {
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001732 *out = Tcl_GetString(((PyTclObject *)in)->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001733 return 1;
1734 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001735 PyErr_Format(PyExc_TypeError,
1736 "must be str, bytes or Tcl_Obj, not %.50s",
1737 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001739}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001740
Benjamin Peterson5879d412009-03-30 14:51:56 +00001741
Martin v. Löwis59683e82008-06-13 07:50:45 +00001742static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001743var_perform(VarEvent *ev)
1744{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001745 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1746 if (!*(ev->res)) {
1747 PyObject *exc, *val, *tb;
1748 PyErr_Fetch(&exc, &val, &tb);
1749 PyErr_NormalizeException(&exc, &val, &tb);
1750 *(ev->exc_type) = exc;
1751 *(ev->exc_val) = val;
Serhiy Storchaka3ec5f422016-10-28 12:14:34 +03001752 Py_XDECREF(tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001753 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001754
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001755}
1756
1757static int
1758var_proc(VarEvent* ev, int flags)
1759{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001760 ENTER_PYTHON
1761 var_perform(ev);
1762 Tcl_MutexLock(&var_mutex);
1763 Tcl_ConditionNotify(ev->cond);
1764 Tcl_MutexUnlock(&var_mutex);
1765 LEAVE_PYTHON
1766 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001767}
1768
Benjamin Peterson5879d412009-03-30 14:51:56 +00001769
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001770static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001771var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001772{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001773 TkappObject *self = (TkappObject*)selfptr;
1774 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 VarEvent *ev;
1776 PyObject *res, *exc_type, *exc_val;
1777 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001778
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001779 /* The current thread is not the interpreter thread. Marshal
1780 the call to the interpreter thread, then wait for
1781 completion. */
1782 if (!WaitForMainloop(self))
1783 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001784
Serhiy Storchaka07940882014-09-11 10:38:54 +03001785 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1786 if (ev == NULL) {
1787 PyErr_NoMemory();
1788 return NULL;
1789 }
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001790 ev->self = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001791 ev->args = args;
1792 ev->flags = flags;
1793 ev->func = func;
1794 ev->res = &res;
1795 ev->exc_type = &exc_type;
1796 ev->exc_val = &exc_val;
1797 ev->cond = &cond;
1798 ev->ev.proc = (Tcl_EventProc*)var_proc;
1799 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1800 Tcl_ConditionFinalize(&cond);
1801 if (!res) {
1802 PyErr_SetObject(exc_type, exc_val);
1803 Py_DECREF(exc_type);
1804 Py_DECREF(exc_val);
1805 return NULL;
1806 }
1807 return res;
1808 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001809 /* Tcl is not threaded, or this is the interpreter thread. */
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001810 return func(self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001811}
1812
Guido van Rossum18468821994-06-20 07:49:28 +00001813static PyObject *
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001814SetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001815{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001816 const char *name1, *name2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001817 PyObject *newValue;
1818 PyObject *res = NULL;
1819 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001820
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001821 switch (PyTuple_GET_SIZE(args)) {
1822 case 2:
1823 if (!PyArg_ParseTuple(args, "O&O:setvar",
1824 varname_converter, &name1, &newValue))
1825 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001826 /* XXX Acquire tcl lock??? */
1827 newval = AsObj(newValue);
1828 if (newval == NULL)
1829 return NULL;
1830 ENTER_TCL
1831 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1832 newval, flags);
1833 ENTER_OVERLAP
1834 if (!ok)
1835 Tkinter_Error(self);
1836 else {
1837 res = Py_None;
1838 Py_INCREF(res);
1839 }
1840 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001841 break;
1842 case 3:
1843 if (!PyArg_ParseTuple(args, "ssO:setvar",
1844 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001845 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001846 CHECK_STRING_LENGTH(name1);
1847 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001848 /* XXX must hold tcl lock already??? */
1849 newval = AsObj(newValue);
1850 ENTER_TCL
1851 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1852 ENTER_OVERLAP
1853 if (!ok)
1854 Tkinter_Error(self);
1855 else {
1856 res = Py_None;
1857 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001858 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001859 LEAVE_OVERLAP_TCL
1860 break;
1861 default:
1862 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1863 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001864 }
1865 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001866}
1867
1868static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001869Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001870{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001871 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001872}
1873
1874static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001875Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001876{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001877 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001878}
1879
Barry Warsawfa701a81997-01-16 00:15:11 +00001880
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001881
Guido van Rossum18468821994-06-20 07:49:28 +00001882static PyObject *
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001883GetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001884{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001885 const char *name1, *name2=NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001886 PyObject *res = NULL;
1887 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001888
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001889 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1890 varname_converter, &name1, &name2))
1891 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001892
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001893 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001894 ENTER_TCL
1895 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1896 ENTER_OVERLAP
1897 if (tres == NULL) {
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001898 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001899 } else {
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001900 if (self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001901 res = FromObj(self, tres);
1902 }
1903 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001904 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001905 }
1906 }
1907 LEAVE_OVERLAP_TCL
1908 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001909}
1910
1911static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001912Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001913{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001914 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001915}
1916
1917static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001918Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001919{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001920 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001921}
1922
Barry Warsawfa701a81997-01-16 00:15:11 +00001923
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001924
Guido van Rossum18468821994-06-20 07:49:28 +00001925static PyObject *
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001926UnsetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001927{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001928 char *name1, *name2=NULL;
1929 int code;
1930 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001931
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001932 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1933 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001934
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001935 CHECK_STRING_LENGTH(name1);
1936 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001937 ENTER_TCL
1938 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1939 ENTER_OVERLAP
1940 if (code == TCL_ERROR)
1941 res = Tkinter_Error(self);
1942 else {
1943 Py_INCREF(Py_None);
1944 res = Py_None;
1945 }
1946 LEAVE_OVERLAP_TCL
1947 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001948}
1949
1950static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001951Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001952{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001953 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001954}
1955
1956static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001957Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001958{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001959 return var_invoke(UnsetVar, self, args,
1960 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001961}
1962
Barry Warsawfa701a81997-01-16 00:15:11 +00001963
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001964
Guido van Rossum18468821994-06-20 07:49:28 +00001965/** Tcl to Python **/
1966
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001967/*[clinic input]
1968_tkinter.tkapp.getint
1969
1970 arg: object
1971 /
1972
1973[clinic start generated code]*/
1974
Guido van Rossum18468821994-06-20 07:49:28 +00001975static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001976_tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
1977/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001978{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001979 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001980 Tcl_Obj *value;
1981 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00001982
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001983 if (PyLong_Check(arg)) {
1984 Py_INCREF(arg);
1985 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001986 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001987
Serhiy Storchaka645058d2015-05-06 14:00:04 +03001988 if (PyTclObject_Check(arg)) {
1989 value = ((PyTclObject*)arg)->value;
1990 Tcl_IncrRefCount(value);
1991 }
1992 else {
1993 if (!PyArg_Parse(arg, "s:getint", &s))
1994 return NULL;
1995 CHECK_STRING_LENGTH(s);
1996 value = Tcl_NewStringObj(s, -1);
1997 if (value == NULL)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07001998 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03001999 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002000 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
2001 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
2002
2003 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
2004 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
2005 */
2006#ifdef HAVE_LIBTOMMAMTH
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002007 result = fromBignumObj(self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002008#else
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002009 result = fromWideIntObj(self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002010#endif
2011 Tcl_DecrRefCount(value);
2012 if (result != NULL || PyErr_Occurred())
2013 return result;
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002014 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00002015}
2016
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002017/*[clinic input]
2018_tkinter.tkapp.getdouble
2019
2020 arg: object
2021 /
2022
2023[clinic start generated code]*/
2024
Guido van Rossum18468821994-06-20 07:49:28 +00002025static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002026_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
2027/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002028{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002029 char *s;
2030 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00002031
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002032 if (PyFloat_Check(arg)) {
2033 Py_INCREF(arg);
2034 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002035 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002036
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002037 if (PyNumber_Check(arg)) {
2038 return PyNumber_Float(arg);
2039 }
2040
2041 if (PyTclObject_Check(arg)) {
2042 if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
2043 ((PyTclObject*)arg)->value,
2044 &v) == TCL_ERROR)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002045 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002046 return PyFloat_FromDouble(v);
2047 }
2048
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002049 if (!PyArg_Parse(arg, "s:getdouble", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002050 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002051 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002052 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002053 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002054 return PyFloat_FromDouble(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002055}
2056
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002057/*[clinic input]
2058_tkinter.tkapp.getboolean
2059
2060 arg: object
2061 /
2062
2063[clinic start generated code]*/
2064
Guido van Rossum18468821994-06-20 07:49:28 +00002065static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002066_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
2067/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002068{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002069 char *s;
2070 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002071
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002072 if (PyLong_Check(arg)) { /* int or bool */
2073 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002074 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002075
2076 if (PyTclObject_Check(arg)) {
2077 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2078 ((PyTclObject*)arg)->value,
2079 &v) == TCL_ERROR)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002080 return Tkinter_Error(self);
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002081 return PyBool_FromLong(v);
2082 }
2083
2084 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002085 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002086 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002087 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002088 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002089 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002090}
2091
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002092/*[clinic input]
2093_tkinter.tkapp.exprstring
2094
2095 s: str
2096 /
2097
2098[clinic start generated code]*/
2099
Guido van Rossum18468821994-06-20 07:49:28 +00002100static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002101_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2102/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002103{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002104 PyObject *res = NULL;
2105 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002106
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002107 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002108 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002109
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002110 ENTER_TCL
2111 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2112 ENTER_OVERLAP
2113 if (retval == TCL_ERROR)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002114 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115 else
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002116 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002117 LEAVE_OVERLAP_TCL
2118 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002119}
2120
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002121/*[clinic input]
2122_tkinter.tkapp.exprlong
2123
2124 s: str
2125 /
2126
2127[clinic start generated code]*/
2128
Guido van Rossum18468821994-06-20 07:49:28 +00002129static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002130_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2131/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002132{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002133 PyObject *res = NULL;
2134 int retval;
2135 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002136
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002137 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002139
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002140 ENTER_TCL
2141 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2142 ENTER_OVERLAP
2143 if (retval == TCL_ERROR)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002144 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002145 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002146 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002147 LEAVE_OVERLAP_TCL
2148 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002149}
2150
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002151/*[clinic input]
2152_tkinter.tkapp.exprdouble
2153
2154 s: str
2155 /
2156
2157[clinic start generated code]*/
2158
Guido van Rossum18468821994-06-20 07:49:28 +00002159static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002160_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2161/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002162{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002163 PyObject *res = NULL;
2164 double v;
2165 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002166
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002167 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002168 CHECK_TCL_APPARTMENT;
2169 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2170 ENTER_TCL
2171 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2172 ENTER_OVERLAP
2173 PyFPE_END_PROTECT(retval)
2174 if (retval == TCL_ERROR)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002175 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002176 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002177 res = PyFloat_FromDouble(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002178 LEAVE_OVERLAP_TCL
2179 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002180}
2181
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002182/*[clinic input]
2183_tkinter.tkapp.exprboolean
2184
2185 s: str
2186 /
2187
2188[clinic start generated code]*/
2189
Guido van Rossum18468821994-06-20 07:49:28 +00002190static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002191_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2192/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002193{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002194 PyObject *res = NULL;
2195 int retval;
2196 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002197
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002198 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002199 CHECK_TCL_APPARTMENT;
2200 ENTER_TCL
2201 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2202 ENTER_OVERLAP
2203 if (retval == TCL_ERROR)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002204 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002205 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002206 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002207 LEAVE_OVERLAP_TCL
2208 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002209}
2210
Barry Warsawfa701a81997-01-16 00:15:11 +00002211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002212
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002213/*[clinic input]
2214_tkinter.tkapp.splitlist
2215
2216 arg: object
2217 /
2218
2219[clinic start generated code]*/
2220
Guido van Rossum18468821994-06-20 07:49:28 +00002221static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002222_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2223/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002224{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002225 char *list;
2226 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002227 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002228 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002229 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002230
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002231 if (PyTclObject_Check(arg)) {
2232 int objc;
2233 Tcl_Obj **objv;
2234 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2235 ((PyTclObject*)arg)->value,
2236 &objc, &objv) == TCL_ERROR) {
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002237 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002238 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002239 if (!(v = PyTuple_New(objc)))
2240 return NULL;
2241 for (i = 0; i < objc; i++) {
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002242 PyObject *s = FromObj(self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002243 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002244 Py_DECREF(v);
2245 return NULL;
2246 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002247 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002248 }
2249 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002250 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002251 if (PyTuple_Check(arg)) {
2252 Py_INCREF(arg);
2253 return arg;
2254 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002255 if (PyList_Check(arg)) {
2256 return PySequence_Tuple(arg);
2257 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002258
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002259 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002260 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002261
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002262 if (strlen(list) >= INT_MAX) {
2263 PyErr_SetString(PyExc_OverflowError, "string is too long");
2264 PyMem_Free(list);
2265 return NULL;
2266 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002267 if (Tcl_SplitList(Tkapp_Interp(self), list,
2268 &argc, &argv) == TCL_ERROR) {
2269 PyMem_Free(list);
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002270 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002271 }
Guido van Rossum18468821994-06-20 07:49:28 +00002272
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002273 if (!(v = PyTuple_New(argc)))
2274 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002275
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002276 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002277 PyObject *s = unicodeFromTclString(argv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002278 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002279 Py_DECREF(v);
2280 v = NULL;
2281 goto finally;
2282 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002283 PyTuple_SET_ITEM(v, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002284 }
Guido van Rossum18468821994-06-20 07:49:28 +00002285
Barry Warsawfa701a81997-01-16 00:15:11 +00002286 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002287 ckfree(FREECAST argv);
2288 PyMem_Free(list);
2289 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002290}
2291
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002292/*[clinic input]
2293_tkinter.tkapp.split
2294
2295 arg: object
2296 /
2297
2298[clinic start generated code]*/
2299
Guido van Rossum18468821994-06-20 07:49:28 +00002300static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002301_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2302/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002303{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002304 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002305 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002306
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002307 if (PyTclObject_Check(arg)) {
2308 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2309 int objc;
2310 Tcl_Obj **objv;
2311 int i;
2312 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2313 &objc, &objv) == TCL_ERROR) {
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002314 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002315 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002316 if (objc == 0)
2317 return PyUnicode_FromString("");
2318 if (objc == 1)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002319 return FromObj(self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002320 if (!(v = PyTuple_New(objc)))
2321 return NULL;
2322 for (i = 0; i < objc; i++) {
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002323 PyObject *s = FromObj(self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002324 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002325 Py_DECREF(v);
2326 return NULL;
2327 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002328 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002329 }
2330 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002331 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002332 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002333 return SplitObj(arg);
2334
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002335 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002336 return NULL;
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002337 if (strlen(list) >= INT_MAX) {
2338 PyErr_SetString(PyExc_OverflowError, "string is too long");
2339 PyMem_Free(list);
2340 return NULL;
2341 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002342 v = Split(list);
2343 PyMem_Free(list);
2344 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002345}
2346
Barry Warsawfa701a81997-01-16 00:15:11 +00002347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002348
Guido van Rossum18468821994-06-20 07:49:28 +00002349/** Tcl Command **/
2350
Guido van Rossum00d93061998-05-28 23:06:38 +00002351/* Client data struct */
2352typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002353 PyObject *self;
2354 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002355} PythonCmd_ClientData;
2356
2357static int
Fred Drake509d79a2000-07-08 04:04:38 +00002358PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002359{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002360 errorInCmd = 1;
2361 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2362 LEAVE_PYTHON
2363 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002364}
2365
Guido van Rossum18468821994-06-20 07:49:28 +00002366/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002367 * function or method.
2368 */
Guido van Rossum18468821994-06-20 07:49:28 +00002369static int
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002370PythonCmd(ClientData clientData, Tcl_Interp *interp,
2371 int objc, Tcl_Obj *const objv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002372{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002373 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002374 PyObject *args, *res;
2375 int i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002376 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002377
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002378 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002379
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002380 /* Create argument tuple (objv1, ..., objvN) */
2381 if (!(args = PyTuple_New(objc - 1)))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002382 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002383
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002384 for (i = 0; i < (objc - 1); i++) {
2385 PyObject *s = unicodeFromTclObj(objv[i + 1]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002386 if (!s) {
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002387 Py_DECREF(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002388 return PythonCmd_Error(interp);
2389 }
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002390 PyTuple_SET_ITEM(args, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002391 }
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002392
2393 res = PyObject_Call(data->func, args, NULL);
2394 Py_DECREF(args);
Guido van Rossum18468821994-06-20 07:49:28 +00002395
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002396 if (res == NULL)
2397 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002398
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002399 obj_res = AsObj(res);
2400 if (obj_res == NULL) {
2401 Py_DECREF(res);
2402 return PythonCmd_Error(interp);
2403 }
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002404 Tcl_SetObjResult(interp, obj_res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002405 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002408
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002409 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +00002410}
2411
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002412
Guido van Rossum18468821994-06-20 07:49:28 +00002413static void
Fred Drake509d79a2000-07-08 04:04:38 +00002414PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002415{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002416 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002417
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002418 ENTER_PYTHON
2419 Py_XDECREF(data->self);
2420 Py_XDECREF(data->func);
2421 PyMem_DEL(data);
2422 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002423}
2424
Barry Warsawfa701a81997-01-16 00:15:11 +00002425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002426
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002427
2428TCL_DECLARE_MUTEX(command_mutex)
2429
2430typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002431 Tcl_Event ev;
2432 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002433 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002434 int create;
2435 int *status;
2436 ClientData *data;
2437 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002438} CommandEvent;
2439
2440static int
2441Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002442{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002443 if (ev->create)
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002444 *ev->status = Tcl_CreateObjCommand(
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002445 ev->interp, ev->name, PythonCmd,
2446 ev->data, PythonCmdDelete) == NULL;
2447 else
2448 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2449 Tcl_MutexLock(&command_mutex);
2450 Tcl_ConditionNotify(ev->done);
2451 Tcl_MutexUnlock(&command_mutex);
2452 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002453}
2454
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002455/*[clinic input]
2456_tkinter.tkapp.createcommand
2457
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002458 name: str
2459 func: object
2460 /
2461
2462[clinic start generated code]*/
2463
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002464static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002465_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2466 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002467/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002468{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002469 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002470 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002471
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002472 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002473 if (!PyCallable_Check(func)) {
2474 PyErr_SetString(PyExc_TypeError, "command not callable");
2475 return NULL;
2476 }
Guido van Rossum18468821994-06-20 07:49:28 +00002477
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002478 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2479 !WaitForMainloop(self))
2480 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002481
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002482 data = PyMem_NEW(PythonCmd_ClientData, 1);
2483 if (!data)
2484 return PyErr_NoMemory();
2485 Py_INCREF(self);
2486 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002487 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002488 data->func = func;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002489 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2490 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002491 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2492 if (ev == NULL) {
2493 PyErr_NoMemory();
2494 PyMem_DEL(data);
2495 return NULL;
2496 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002497 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2498 ev->interp = self->interp;
2499 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002500 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002501 ev->data = (ClientData)data;
2502 ev->status = &err;
2503 ev->done = &cond;
2504 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2505 Tcl_ConditionFinalize(&cond);
2506 }
2507 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 {
2509 ENTER_TCL
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002510 err = Tcl_CreateObjCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002511 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002512 (ClientData)data, PythonCmdDelete) == NULL;
2513 LEAVE_TCL
2514 }
2515 if (err) {
2516 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2517 PyMem_DEL(data);
2518 return NULL;
2519 }
Guido van Rossum18468821994-06-20 07:49:28 +00002520
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002521 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002522}
2523
Barry Warsawfa701a81997-01-16 00:15:11 +00002524
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002525
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002526/*[clinic input]
2527_tkinter.tkapp.deletecommand
2528
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002529 name: str
2530 /
2531
2532[clinic start generated code]*/
2533
Guido van Rossum18468821994-06-20 07:49:28 +00002534static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002535_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002536/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002537{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002538 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002539
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002540 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002541
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002542 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2543 Tcl_Condition cond = NULL;
2544 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002545 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2546 if (ev == NULL) {
2547 PyErr_NoMemory();
2548 return NULL;
2549 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002550 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2551 ev->interp = self->interp;
2552 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002553 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002554 ev->status = &err;
2555 ev->done = &cond;
2556 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2557 &command_mutex);
2558 Tcl_ConditionFinalize(&cond);
2559 }
2560 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002561 {
2562 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002563 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002564 LEAVE_TCL
2565 }
2566 if (err == -1) {
2567 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2568 return NULL;
2569 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002570 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002571}
2572
Barry Warsawfa701a81997-01-16 00:15:11 +00002573
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002574
Guido van Rossum00d93061998-05-28 23:06:38 +00002575#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002576/** File Handler **/
2577
Guido van Rossum00d93061998-05-28 23:06:38 +00002578typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579 PyObject *func;
2580 PyObject *file;
2581 int id;
2582 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002583} FileHandler_ClientData;
2584
2585static FileHandler_ClientData *HeadFHCD;
2586
2587static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002588NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002589{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002590 FileHandler_ClientData *p;
2591 p = PyMem_NEW(FileHandler_ClientData, 1);
2592 if (p != NULL) {
2593 Py_XINCREF(func);
2594 Py_XINCREF(file);
2595 p->func = func;
2596 p->file = file;
2597 p->id = id;
2598 p->next = HeadFHCD;
2599 HeadFHCD = p;
2600 }
2601 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002602}
2603
2604static void
Fred Drake509d79a2000-07-08 04:04:38 +00002605DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002606{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002607 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002608
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002609 pp = &HeadFHCD;
2610 while ((p = *pp) != NULL) {
2611 if (p->id == id) {
2612 *pp = p->next;
2613 Py_XDECREF(p->func);
2614 Py_XDECREF(p->file);
2615 PyMem_DEL(p);
2616 }
2617 else
2618 pp = &p->next;
2619 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002620}
2621
Guido van Rossuma597dde1995-01-10 20:56:29 +00002622static void
Fred Drake509d79a2000-07-08 04:04:38 +00002623FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002624{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002625 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
INADA Naoki72dccde2017-02-16 09:26:01 +09002626 PyObject *func, *file, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002628 ENTER_PYTHON
2629 func = data->func;
2630 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002631
INADA Naoki72dccde2017-02-16 09:26:01 +09002632 res = PyObject_CallFunction(func, "Oi", file, mask);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002633 if (res == NULL) {
2634 errorInCmd = 1;
2635 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2636 }
2637 Py_XDECREF(res);
2638 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002639}
2640
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002641/*[clinic input]
2642_tkinter.tkapp.createfilehandler
2643
2644 file: object
2645 mask: int
2646 func: object
2647 /
2648
2649[clinic start generated code]*/
2650
Guido van Rossum18468821994-06-20 07:49:28 +00002651static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002652_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2653 int mask, PyObject *func)
2654/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002655{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002656 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002657 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002659 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002661 tfile = PyObject_AsFileDescriptor(file);
2662 if (tfile < 0)
2663 return NULL;
2664 if (!PyCallable_Check(func)) {
2665 PyErr_SetString(PyExc_TypeError, "bad argument list");
2666 return NULL;
2667 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002669 data = NewFHCD(func, file, tfile);
2670 if (data == NULL)
2671 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002673 /* Ought to check for null Tcl_File object... */
2674 ENTER_TCL
2675 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2676 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002677 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002678}
2679
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002680/*[clinic input]
2681_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002682
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002683 file: object
2684 /
2685
2686[clinic start generated code]*/
2687
2688static PyObject *
2689_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2690/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2691{
2692 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002694 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002696 tfile = PyObject_AsFileDescriptor(file);
2697 if (tfile < 0)
2698 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002700 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002702 /* Ought to check for null Tcl_File object... */
2703 ENTER_TCL
2704 Tcl_DeleteFileHandler(tfile);
2705 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002706 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002707}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002708#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002709
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002710
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002711/**** Tktt Object (timer token) ****/
2712
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002713static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002714
Guido van Rossum00d93061998-05-28 23:06:38 +00002715typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002716 PyObject_HEAD
2717 Tcl_TimerToken token;
2718 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002719} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002720
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002721/*[clinic input]
2722_tkinter.tktimertoken.deletetimerhandler
2723
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002724[clinic start generated code]*/
2725
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002726static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002727_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002728/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002729{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002730 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002731 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002732
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002733 if (v->token != NULL) {
2734 Tcl_DeleteTimerHandler(v->token);
2735 v->token = NULL;
2736 }
2737 if (func != NULL) {
2738 v->func = NULL;
2739 Py_DECREF(func);
2740 Py_DECREF(v); /* See Tktt_New() */
2741 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002742 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002743}
2744
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002745static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002746Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002747{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002748 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002749
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002750 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002751 if (v == NULL)
2752 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002753
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002754 Py_INCREF(func);
2755 v->token = NULL;
2756 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002757
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002758 /* Extra reference, deleted when called or when handler is deleted */
2759 Py_INCREF(v);
2760 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002761}
2762
2763static void
Fred Drake509d79a2000-07-08 04:04:38 +00002764Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002765{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002766 TkttObject *v = (TkttObject *)self;
2767 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002768 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002769
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002770 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002771
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002772 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002773 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002774}
2775
Guido van Rossum597ac201998-05-12 14:36:19 +00002776static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002777Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002778{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002779 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002780 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2781 v,
2782 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002783}
2784
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002785/** Timer Handler **/
2786
2787static void
Fred Drake509d79a2000-07-08 04:04:38 +00002788TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002789{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002790 TkttObject *v = (TkttObject *)clientData;
2791 PyObject *func = v->func;
2792 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002793
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 if (func == NULL)
2795 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002796
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002797 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002798
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002799 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002800
INADA Naoki72dccde2017-02-16 09:26:01 +09002801 res = _PyObject_CallNoArg(func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002802 Py_DECREF(func);
2803 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002804
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002805 if (res == NULL) {
2806 errorInCmd = 1;
2807 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2808 }
2809 else
2810 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002811
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002812 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002813}
2814
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002815/*[clinic input]
2816_tkinter.tkapp.createtimerhandler
2817
2818 milliseconds: int
2819 func: object
2820 /
2821
2822[clinic start generated code]*/
2823
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002824static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002825_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2826 PyObject *func)
2827/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002828{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002829 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002830
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002831 if (!PyCallable_Check(func)) {
2832 PyErr_SetString(PyExc_TypeError, "bad argument list");
2833 return NULL;
2834 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002835
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002836 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002837
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002838 v = Tktt_New(func);
2839 if (v) {
2840 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2841 (ClientData)v);
2842 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002844 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002845}
2846
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002847
Guido van Rossum18468821994-06-20 07:49:28 +00002848/** Event Loop **/
2849
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002850/*[clinic input]
2851_tkinter.tkapp.mainloop
2852
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002853 threshold: int = 0
2854 /
2855
2856[clinic start generated code]*/
2857
Guido van Rossum18468821994-06-20 07:49:28 +00002858static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002859_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002860/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002861{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002862 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002863
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002864 CHECK_TCL_APPARTMENT;
2865 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002866
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002867 quitMainLoop = 0;
2868 while (Tk_GetNumMainWindows() > threshold &&
2869 !quitMainLoop &&
2870 !errorInCmd)
2871 {
2872 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002873
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002874 if (self->threaded) {
2875 /* Allow other Python threads to run. */
2876 ENTER_TCL
2877 result = Tcl_DoOneEvent(0);
2878 LEAVE_TCL
2879 }
2880 else {
2881 Py_BEGIN_ALLOW_THREADS
2882 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2883 tcl_tstate = tstate;
2884 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2885 tcl_tstate = NULL;
2886 if(tcl_lock)PyThread_release_lock(tcl_lock);
2887 if (result == 0)
2888 Sleep(Tkinter_busywaitinterval);
2889 Py_END_ALLOW_THREADS
2890 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002891
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002892 if (PyErr_CheckSignals() != 0) {
2893 self->dispatching = 0;
2894 return NULL;
2895 }
2896 if (result < 0)
2897 break;
2898 }
2899 self->dispatching = 0;
2900 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002901
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002902 if (errorInCmd) {
2903 errorInCmd = 0;
2904 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2905 excInCmd = valInCmd = trbInCmd = NULL;
2906 return NULL;
2907 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002908 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002909}
2910
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002911/*[clinic input]
2912_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002913
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002914 flags: int = 0
2915 /
2916
2917[clinic start generated code]*/
2918
2919static PyObject *
2920_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2921/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2922{
2923 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002924
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002925 ENTER_TCL
2926 rv = Tcl_DoOneEvent(flags);
2927 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002928 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002929}
2930
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002931/*[clinic input]
2932_tkinter.tkapp.quit
2933[clinic start generated code]*/
2934
Guido van Rossum062cfb01995-01-10 17:42:51 +00002935static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002936_tkinter_tkapp_quit_impl(TkappObject *self)
2937/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002938{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002939 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002940 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002941}
2942
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002943/*[clinic input]
2944_tkinter.tkapp.interpaddr
2945[clinic start generated code]*/
2946
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002947static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002948_tkinter_tkapp_interpaddr_impl(TkappObject *self)
2949/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002950{
Victor Stinnere1040e22013-09-05 00:22:24 +02002951 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002952}
2953
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002954/*[clinic input]
2955_tkinter.tkapp.loadtk
2956[clinic start generated code]*/
2957
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002958static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002959_tkinter_tkapp_loadtk_impl(TkappObject *self)
2960/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00002961{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002962 Tcl_Interp *interp = Tkapp_Interp(self);
2963 const char * _tk_exists = NULL;
2964 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002965
Guilherme Polob681df42009-02-09 22:33:59 +00002966#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002967 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2968 * first call failed.
2969 * To avoid the deadlock, we just refuse the second call through
2970 * a static variable.
2971 */
2972 if (tk_load_failed) {
2973 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2974 return NULL;
2975 }
Guilherme Polob681df42009-02-09 22:33:59 +00002976#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002977
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002978 /* We want to guard against calling Tk_Init() multiple times */
2979 CHECK_TCL_APPARTMENT;
2980 ENTER_TCL
2981 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2982 ENTER_OVERLAP
2983 if (err == TCL_ERROR) {
2984 /* This sets an exception, but we cannot return right
2985 away because we need to exit the overlap first. */
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002986 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002987 } else {
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002988 _tk_exists = Tcl_GetStringResult(Tkapp_Interp(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002989 }
2990 LEAVE_OVERLAP_TCL
2991 if (err == TCL_ERROR) {
2992 return NULL;
2993 }
2994 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2995 if (Tk_Init(interp) == TCL_ERROR) {
Miss Islington (bot)dc191242019-10-04 03:28:54 -07002996 Tkinter_Error(self);
Guilherme Polob681df42009-02-09 22:33:59 +00002997#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002998 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002999#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003000 return NULL;
3001 }
3002 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003003 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00003004}
Barry Warsawfa701a81997-01-16 00:15:11 +00003005
Martin v. Löwisffad6332002-11-26 09:28:05 +00003006static PyObject *
3007Tkapp_WantObjects(PyObject *self, PyObject *args)
3008{
3009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003010 int wantobjects = -1;
3011 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3012 return NULL;
3013 if (wantobjects == -1)
3014 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3015 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003016
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003017 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003018}
3019
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003020/*[clinic input]
3021_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003022
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003023[clinic start generated code]*/
3024
3025static PyObject *
3026_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03003027/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003028{
3029 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003030
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003031 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003032}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003033
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003034
Guido van Rossum18468821994-06-20 07:49:28 +00003035/**** Tkapp Type Methods ****/
3036
3037static void
Fred Drake509d79a2000-07-08 04:04:38 +00003038Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003039{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003040 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003041 /*CHECK_TCL_APPARTMENT;*/
3042 ENTER_TCL
3043 Tcl_DeleteInterp(Tkapp_Interp(self));
3044 LEAVE_TCL
3045 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003046 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003047 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003048}
3049
Barry Warsawfa701a81997-01-16 00:15:11 +00003050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003051
Guido van Rossum18468821994-06-20 07:49:28 +00003052/**** Tkinter Module ****/
3053
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003054typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003055 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003056 Py_ssize_t size; /* current size */
3057 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003058} FlattenContext;
3059
3060static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003061_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003062{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003063 /* expand tuple to hold (at least) size new items.
3064 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003065
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003066 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003067
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003068 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003069 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003071 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003072
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003073 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003074}
3075
3076static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003077_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003078{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003079 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003080
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003081 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003082
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003083 if (depth > 1000) {
3084 PyErr_SetString(PyExc_ValueError,
3085 "nesting too deep in _flatten");
3086 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003087 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3088 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003089 /* preallocate (assume no nesting) */
3090 if (context->size + size > context->maxsize &&
3091 !_bump(context, size))
3092 return 0;
3093 /* copy items to output tuple */
3094 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003095 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003096 if (PyList_Check(o) || PyTuple_Check(o)) {
3097 if (!_flatten1(context, o, depth + 1))
3098 return 0;
3099 } else if (o != Py_None) {
3100 if (context->size + 1 > context->maxsize &&
3101 !_bump(context, 1))
3102 return 0;
3103 Py_INCREF(o);
3104 PyTuple_SET_ITEM(context->tuple,
3105 context->size++, o);
3106 }
3107 }
3108 } else {
3109 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3110 return 0;
3111 }
3112 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003113}
3114
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003115/*[clinic input]
3116_tkinter._flatten
3117
3118 item: object
3119 /
3120
3121[clinic start generated code]*/
3122
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003123static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003124_tkinter__flatten(PyObject *module, PyObject *item)
3125/*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003126{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003127 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003128
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003129 context.maxsize = PySequence_Size(item);
3130 if (context.maxsize < 0)
3131 return NULL;
3132 if (context.maxsize == 0)
3133 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003134
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003135 context.tuple = PyTuple_New(context.maxsize);
3136 if (!context.tuple)
3137 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003138
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003139 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003141 if (!_flatten1(&context, item,0))
3142 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003143
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003144 if (_PyTuple_Resize(&context.tuple, context.size))
3145 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003146
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003147 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003148}
3149
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003150/*[clinic input]
3151_tkinter.create
3152
Serhiy Storchakad322abb2019-09-14 13:31:50 +03003153 screenName: str(accept={str, NoneType}) = None
3154 baseName: str = ""
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003155 className: str = "Tk"
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003156 interactive: bool(accept={int}) = False
3157 wantobjects: bool(accept={int}) = False
3158 wantTk: bool(accept={int}) = True
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003159 if false, then Tk_Init() doesn't get called
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003160 sync: bool(accept={int}) = False
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003161 if true, then pass -sync to wish
Serhiy Storchakad322abb2019-09-14 13:31:50 +03003162 use: str(accept={str, NoneType}) = None
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003163 if not None, then pass -use to wish
3164 /
3165
3166[clinic start generated code]*/
3167
Guido van Rossum18468821994-06-20 07:49:28 +00003168static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003169_tkinter_create_impl(PyObject *module, const char *screenName,
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003170 const char *baseName, const char *className,
3171 int interactive, int wantobjects, int wantTk, int sync,
3172 const char *use)
Serhiy Storchakad322abb2019-09-14 13:31:50 +03003173/*[clinic end generated code: output=e3315607648e6bb4 input=da9b17ee7358d862]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003174{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003175 /* XXX baseName is not used anymore;
3176 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003177 CHECK_STRING_LENGTH(screenName);
3178 CHECK_STRING_LENGTH(baseName);
3179 CHECK_STRING_LENGTH(className);
3180 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003181
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003182 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003183 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003184 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003185}
3186
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003187/*[clinic input]
3188_tkinter.setbusywaitinterval
3189
3190 new_val: int
3191 /
3192
3193Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3194
3195It should be set to a divisor of the maximum time between frames in an animation.
3196[clinic start generated code]*/
3197
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003198static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003199_tkinter_setbusywaitinterval_impl(PyObject *module, int new_val)
3200/*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003201{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003202 if (new_val < 0) {
3203 PyErr_SetString(PyExc_ValueError,
3204 "busywaitinterval must be >= 0");
3205 return NULL;
3206 }
3207 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003208 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003209}
3210
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003211/*[clinic input]
3212_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003213
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003214Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3215[clinic start generated code]*/
3216
3217static int
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003218_tkinter_getbusywaitinterval_impl(PyObject *module)
3219/*[clinic end generated code: output=23b72d552001f5c7 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003220{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003221 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003222}
3223
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003224#include "clinic/_tkinter.c.h"
3225
3226static PyMethodDef Tktt_methods[] =
3227{
3228 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3229 {NULL, NULL}
3230};
3231
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003232static PyType_Slot Tktt_Type_slots[] = {
3233 {Py_tp_dealloc, Tktt_Dealloc},
3234 {Py_tp_repr, Tktt_Repr},
3235 {Py_tp_methods, Tktt_methods},
3236 {0, 0}
3237};
3238
3239static PyType_Spec Tktt_Type_spec = {
3240 "_tkinter.tktimertoken",
3241 sizeof(TkttObject),
3242 0,
3243 Py_TPFLAGS_DEFAULT,
3244 Tktt_Type_slots,
3245};
3246
3247
3248/**** Tkapp Method List ****/
3249
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003250static PyMethodDef Tkapp_methods[] =
3251{
3252 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3253 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3254 {"call", Tkapp_Call, METH_VARARGS},
3255 _TKINTER_TKAPP_EVAL_METHODDEF
3256 _TKINTER_TKAPP_EVALFILE_METHODDEF
3257 _TKINTER_TKAPP_RECORD_METHODDEF
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03003258 _TKINTER_TKAPP_ADDERRORINFO_METHODDEF
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003259 {"setvar", Tkapp_SetVar, METH_VARARGS},
3260 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3261 {"getvar", Tkapp_GetVar, METH_VARARGS},
3262 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3263 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3264 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3265 _TKINTER_TKAPP_GETINT_METHODDEF
3266 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3267 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3268 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3269 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3270 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3271 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3272 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3273 _TKINTER_TKAPP_SPLIT_METHODDEF
3274 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3275 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3276 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3277 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3278 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3279 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3280 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3281 _TKINTER_TKAPP_QUIT_METHODDEF
3282 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3283 _TKINTER_TKAPP_LOADTK_METHODDEF
3284 {NULL, NULL}
3285};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003286
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003287static PyType_Slot Tkapp_Type_slots[] = {
3288 {Py_tp_dealloc, Tkapp_Dealloc},
3289 {Py_tp_methods, Tkapp_methods},
3290 {0, 0}
3291};
3292
3293
3294static PyType_Spec Tkapp_Type_spec = {
3295 "_tkinter.tkapp",
3296 sizeof(TkappObject),
3297 0,
3298 Py_TPFLAGS_DEFAULT,
3299 Tkapp_Type_slots,
3300};
3301
Guido van Rossum18468821994-06-20 07:49:28 +00003302static PyMethodDef moduleMethods[] =
3303{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003304 _TKINTER__FLATTEN_METHODDEF
3305 _TKINTER_CREATE_METHODDEF
3306 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3307 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003308 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003309};
3310
Guido van Rossum7bf15641998-05-22 18:28:17 +00003311#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003312
3313static int stdin_ready = 0;
3314
Guido van Rossumad4db171998-06-13 13:56:28 +00003315#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003316static void
Fred Drake509d79a2000-07-08 04:04:38 +00003317MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003318{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003319 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003320}
Guido van Rossumad4db171998-06-13 13:56:28 +00003321#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003322
Guido van Rossum00d93061998-05-28 23:06:38 +00003323static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003324
Guido van Rossum18468821994-06-20 07:49:28 +00003325static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003326EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003327{
Guido van Rossumad4db171998-06-13 13:56:28 +00003328#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003329 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003330#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003331 PyEval_RestoreThread(event_tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003332 stdin_ready = 0;
3333 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003334#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003335 tfile = fileno(stdin);
3336 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003337#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003338 while (!errorInCmd && !stdin_ready) {
3339 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003340#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003341 if (_kbhit()) {
3342 stdin_ready = 1;
3343 break;
3344 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003345#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003346 Py_BEGIN_ALLOW_THREADS
3347 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3348 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003350 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003352 tcl_tstate = NULL;
3353 if(tcl_lock)PyThread_release_lock(tcl_lock);
3354 if (result == 0)
3355 Sleep(Tkinter_busywaitinterval);
3356 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003357
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003358 if (result < 0)
3359 break;
3360 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003361#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003362 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003363#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003364 if (errorInCmd) {
3365 errorInCmd = 0;
3366 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3367 excInCmd = valInCmd = trbInCmd = NULL;
3368 PyErr_Print();
3369 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003370 PyEval_SaveThread();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003371 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003372}
Guido van Rossum18468821994-06-20 07:49:28 +00003373
Guido van Rossum00d93061998-05-28 23:06:38 +00003374#endif
3375
Guido van Rossum7bf15641998-05-22 18:28:17 +00003376static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003377EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003378{
Guido van Rossum00d93061998-05-28 23:06:38 +00003379#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003380 if (PyOS_InputHook == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003381 event_tstate = PyThreadState_Get();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003382 PyOS_InputHook = EventHook;
3383 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003384#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003385}
3386
3387static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003388DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003389{
Guido van Rossum00d93061998-05-28 23:06:38 +00003390#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003391 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3392 PyOS_InputHook = NULL;
3393 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003394#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003395}
3396
Barry Warsawfa701a81997-01-16 00:15:11 +00003397
Martin v. Löwis1a214512008-06-11 05:26:20 +00003398static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003399 PyModuleDef_HEAD_INIT,
3400 "_tkinter",
3401 NULL,
3402 -1,
3403 moduleMethods,
3404 NULL,
3405 NULL,
3406 NULL,
3407 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003408};
3409
Mark Hammond62b1ab12002-07-23 06:31:15 +00003410PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003411PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003412{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003413 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003414
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003415 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003416 if (tcl_lock == NULL)
3417 return NULL;
Guido van Rossumae92f011996-08-21 19:03:36 +00003418
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003419 m = PyModule_Create(&_tkintermodule);
3420 if (m == NULL)
3421 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003422
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003423 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3424 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003425 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003426 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003427 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003428 Py_INCREF(o);
3429 if (PyModule_AddObject(m, "TclError", o)) {
3430 Py_DECREF(o);
3431 Py_DECREF(m);
3432 return NULL;
3433 }
3434 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003435
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003436 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3437 Py_DECREF(m);
3438 return NULL;
3439 }
3440 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3441 Py_DECREF(m);
3442 return NULL;
3443 }
3444 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3445 Py_DECREF(m);
3446 return NULL;
3447 }
3448 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3449 Py_DECREF(m);
3450 return NULL;
3451 }
3452 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3453 Py_DECREF(m);
3454 return NULL;
3455 }
3456 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3457 Py_DECREF(m);
3458 return NULL;
3459 }
3460 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3461 Py_DECREF(m);
3462 return NULL;
3463 }
3464 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3465 Py_DECREF(m);
3466 return NULL;
3467 }
3468 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3469 Py_DECREF(m);
3470 return NULL;
3471 }
3472 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3473 Py_DECREF(m);
3474 return NULL;
3475 }
3476 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3477 Py_DECREF(m);
3478 return NULL;
3479 }
3480
3481 o = PyType_FromSpec(&Tkapp_Type_spec);
3482 if (o == NULL) {
3483 Py_DECREF(m);
3484 return NULL;
3485 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003486 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003487 if (PyModule_AddObject(m, "TkappType", o)) {
3488 Py_DECREF(o);
3489 Py_DECREF(m);
3490 return NULL;
3491 }
3492 Tkapp_Type = o;
3493
3494 o = PyType_FromSpec(&Tktt_Type_spec);
3495 if (o == NULL) {
3496 Py_DECREF(m);
3497 return NULL;
3498 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003499 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003500 if (PyModule_AddObject(m, "TkttType", o)) {
3501 Py_DECREF(o);
3502 Py_DECREF(m);
3503 return NULL;
3504 }
3505 Tktt_Type = o;
3506
3507 o = PyType_FromSpec(&PyTclObject_Type_spec);
3508 if (o == NULL) {
3509 Py_DECREF(m);
3510 return NULL;
3511 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003512 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003513 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3514 Py_DECREF(o);
3515 Py_DECREF(m);
3516 return NULL;
3517 }
3518 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003519
3520#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003521 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3522 * start waking up. Note that Tcl_FindExecutable will do this, this
3523 * code must be above it! The original warning from
3524 * tkMacOSXAppInit.c is copied below.
3525 *
3526 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3527 * Tcl interpreter for now. It probably should work to do this
3528 * in the other order, but for now it doesn't seem to.
3529 *
3530 */
3531 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003532#endif
3533
3534
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003535 /* This helps the dynamic loader; in Unicode aware Tcl versions
3536 it also helps Tcl find its encodings. */
3537 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3538 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003539 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003540 if (cexe) {
3541#ifdef MS_WINDOWS
3542 int set_var = 0;
3543 PyObject *str_path;
3544 wchar_t *wcs_path;
3545 DWORD ret;
3546
3547 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3548
3549 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3550 str_path = _get_tcl_lib_path();
3551 if (str_path == NULL && PyErr_Occurred()) {
3552 return NULL;
3553 }
3554 if (str_path != NULL) {
3555 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3556 if (wcs_path == NULL) {
3557 return NULL;
3558 }
3559 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3560 set_var = 1;
3561 }
3562 }
3563
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003564 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003565
3566 if (set_var) {
3567 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3568 PyMem_Free(wcs_path);
3569 }
3570#else
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003571 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003572#endif /* MS_WINDOWS */
3573 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003574 Py_XDECREF(cexe);
3575 Py_DECREF(uexe);
3576 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003578 if (PyErr_Occurred()) {
3579 Py_DECREF(m);
3580 return NULL;
3581 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003582
Guido van Rossum43ff8681998-07-14 18:02:13 +00003583#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003584 /* This was not a good idea; through <Destroy> bindings,
3585 Tcl_Finalize() may invoke Python code but at that point the
3586 interpreter and thread state have already been destroyed! */
3587 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003588#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003589 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003590}