blob: 329b291729d581b1fcef17a59c629e3ada288f5c [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 Rossum2a5119b1998-05-29 01:28:40 +000029#ifdef MS_WINDOWS
30#include <windows.h>
31#endif
32
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030033#define CHECK_SIZE(size, elemsize) \
Serhiy Storchaka26861b02015-02-16 20:52:17 +020034 ((size_t)(size) <= Py_MIN((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030035
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000036/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
37 it always; if Tcl is not threaded, the thread functions in
38 Tcl are empty. */
39#define TCL_THREADS
40
Jack Jansencb852442001-12-09 23:15:56 +000041#ifdef TK_FRAMEWORK
42#include <Tcl/tcl.h>
43#include <Tk/tk.h>
44#else
Guido van Rossum18468821994-06-20 07:49:28 +000045#include <tcl.h>
46#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000047#endif
Guido van Rossum18468821994-06-20 07:49:28 +000048
Guilherme Polo2d87e422009-04-10 22:19:09 +000049#include "tkinter.h"
50
Serhiy Storchaka71b49dd2015-04-22 10:59:32 +030051#if TK_HEX_VERSION < 0x08040200
Serhiy Storchaka6716d602014-07-30 19:19:21 +030052#error "Tk older than 8.4 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000053#endif
54
Serhiy Storchaka3af7a382015-04-22 10:53:08 +030055#if TK_HEX_VERSION >= 0x08050208 && TK_HEX_VERSION < 0x08060000 || \
56 TK_HEX_VERSION >= 0x08060200
Andrew York003708b2020-05-15 03:43:58 -070057#define HAVE_LIBTOMMATH
Serhiy Storchakaea134da2015-04-02 18:46:50 +030058#include <tclTomMath.h>
59#endif
60
Jack Janseneddc1442003-11-20 01:44:59 +000061#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000062#define HAVE_CREATEFILEHANDLER
63#endif
64
Guido van Rossum00d93061998-05-28 23:06:38 +000065#ifdef HAVE_CREATEFILEHANDLER
66
Neal Norwitzd948a432006-01-08 01:08:55 +000067/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
68 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
69#ifndef TCL_UNIX_FD
70# ifdef TCL_WIN_SOCKET
71# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
72# else
73# define TCL_UNIX_FD 1
74# endif
75#endif
76
Guido van Rossum00d93061998-05-28 23:06:38 +000077/* Tcl_CreateFileHandler() changed several times; these macros deal with the
78 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
79 Unix, only because Jack added it back); when available on Windows, it only
80 applies to sockets. */
81
Guido van Rossum7bf15641998-05-22 18:28:17 +000082#ifdef MS_WINDOWS
83#define FHANDLETYPE TCL_WIN_SOCKET
84#else
85#define FHANDLETYPE TCL_UNIX_FD
86#endif
87
Guido van Rossum00d93061998-05-28 23:06:38 +000088/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
89 which uses this to handle Tcl events while the user is typing commands. */
90
91#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +000092#define WAIT_FOR_STDIN
93#endif
94
Guido van Rossum00d93061998-05-28 23:06:38 +000095#endif /* HAVE_CREATEFILEHANDLER */
96
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +030097/* Use OS native encoding for converting between Python strings and
98 Tcl objects.
99 On Windows use UTF-16 (or UTF-32 for 32-bit Tcl_UniChar) with the
100 "surrogatepass" error handler for converting to/from Tcl Unicode objects.
101 On Linux use UTF-8 with the "surrogateescape" error handler for converting
102 to/from Tcl String objects. */
103#ifdef MS_WINDOWS
104#define USE_TCL_UNICODE 1
105#else
106#define USE_TCL_UNICODE 0
107#endif
108
109#if PY_LITTLE_ENDIAN
110#define NATIVE_BYTEORDER -1
111#else
112#define NATIVE_BYTEORDER 1
113#endif
114
Guido van Rossumad4db171998-06-13 13:56:28 +0000115#ifdef MS_WINDOWS
116#include <conio.h>
117#define WAIT_FOR_STDIN
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500118
119static PyObject *
120_get_tcl_lib_path()
121{
122 static PyObject *tcl_library_path = NULL;
123 static int already_checked = 0;
124
125 if (already_checked == 0) {
126 PyObject *prefix;
127 struct stat stat_buf;
128 int stat_return_value;
129
130 prefix = PyUnicode_FromWideChar(Py_GetPrefix(), -1);
131 if (prefix == NULL) {
132 return NULL;
133 }
134
135 /* Check expected location for an installed Python first */
136 tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION);
137 if (tcl_library_path == NULL) {
138 return NULL;
139 }
140 tcl_library_path = PyUnicode_Concat(prefix, tcl_library_path);
141 if (tcl_library_path == NULL) {
142 return NULL;
143 }
144 stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
145 if (stat_return_value == -2) {
146 return NULL;
147 }
148 if (stat_return_value == -1) {
149 /* install location doesn't exist, reset errno and see if
150 we're a repository build */
151 errno = 0;
152#ifdef Py_TCLTK_DIR
153 tcl_library_path = PyUnicode_FromString(
154 Py_TCLTK_DIR "\\lib\\tcl" TCL_VERSION);
155 if (tcl_library_path == NULL) {
156 return NULL;
157 }
158 stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
159 if (stat_return_value == -2) {
160 return NULL;
161 }
162 if (stat_return_value == -1) {
163 /* tcltkDir for a repository build doesn't exist either,
164 reset errno and leave Tcl to its own devices */
165 errno = 0;
166 tcl_library_path = NULL;
167 }
168#else
169 tcl_library_path = NULL;
Guido van Rossumad4db171998-06-13 13:56:28 +0000170#endif
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500171 }
172 already_checked = 1;
173 }
174 return tcl_library_path;
175}
176#endif /* MS_WINDOWS */
Guido van Rossumad4db171998-06-13 13:56:28 +0000177
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000178/* The threading situation is complicated. Tcl is not thread-safe, except
179 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000180
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300181 So we need to use a lock around all uses of Tcl. Previously, the
182 Python interpreter lock was used for this. However, this causes
183 problems when other Python threads need to run while Tcl is blocked
184 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000185
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300186 To solve this problem, a separate lock for Tcl is introduced.
187 Holding it is incompatible with holding Python's interpreter lock.
188 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000189
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300190 ENTER_TCL and LEAVE_TCL are brackets, just like
191 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
192 used whenever a call into Tcl is made that could call an event
193 handler, or otherwise affect the state of a Tcl interpreter. These
194 assume that the surrounding code has the Python interpreter lock;
195 inside the brackets, the Python interpreter lock has been released
196 and the lock for Tcl has been acquired.
197
198 Sometimes, it is necessary to have both the Python lock and the Tcl
199 lock. (For example, when transferring data from the Tcl
200 interpreter result to a Python string object.) This can be done by
201 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
202 reacquires the Python lock (and restores the thread state) but
203 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
204 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000205
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000206 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300207 handlers when the handler needs to use Python. Such event handlers
208 are entered while the lock for Tcl is held; the event handler
209 presumably needs to use Python. ENTER_PYTHON releases the lock for
210 Tcl and acquires the Python interpreter lock, restoring the
211 appropriate thread state, and LEAVE_PYTHON releases the Python
212 interpreter lock and re-acquires the lock for Tcl. It is okay for
213 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
214 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300216 These locks expand to several statements and brackets; they should
217 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000218
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300219 If Tcl is threaded, this approach won't work anymore. The Tcl
220 interpreter is only valid in the thread that created it, and all Tk
221 activity must happen in this thread, also. That means that the
222 mainloop must be invoked in the thread that created the
223 interpreter. Invoking commands from other threads is possible;
224 _tkinter will queue an event for the interpreter thread, which will
225 then execute the command and pass back the result. If the main
226 thread is not in the mainloop, and invoking commands causes an
227 exception; if the main loop is running but not processing events,
228 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000229
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300230 In addition, for a threaded Tcl, a single global tcl_tstate won't
231 be sufficient anymore, since multiple Tcl interpreters may
232 simultaneously dispatch in different threads. So we use the Tcl TLS
233 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000234
Guido van Rossum00d93061998-05-28 23:06:38 +0000235*/
236
Guido van Rossum65d5b571998-12-21 19:32:43 +0000237static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000238
239#ifdef TCL_THREADS
240static Tcl_ThreadDataKey state_key;
241typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300242#define tcl_tstate \
243 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000244#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000245static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000246#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000247
248#define ENTER_TCL \
Miss Islington (bot)46f96f02021-05-19 11:46:45 -0700249 { PyThreadState *tstate = PyThreadState_Get(); \
250 Py_BEGIN_ALLOW_THREADS \
251 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); \
252 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; \
Miss Islington (bot)46f96f02021-05-19 11:46:45 -0700256 if(tcl_lock)PyThread_release_lock(tcl_lock); \
257 Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000258
Guido van Rossum62320c91998-06-15 04:36:09 +0000259#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000261
262#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000263 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000264
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000265#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000266 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Miss Islington (bot)46f96f02021-05-19 11:46:45 -0700267 if(tcl_lock) \
268 PyThread_release_lock(tcl_lock); \
269 PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000270
271#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000272 { PyThreadState *tstate = PyEval_SaveThread(); \
Miss Islington (bot)46f96f02021-05-19 11:46:45 -0700273 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); \
274 tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000275
276#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000277 if (((TkappObject *)self)->threaded && \
278 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300279 PyErr_SetString(PyExc_RuntimeError, \
luzpaza5293b42017-11-05 07:37:50 -0600280 "Calling Tcl from different apartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000281 return 0; \
282 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000283
Guido van Rossum97867b21996-08-08 19:09:53 +0000284#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000285#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000286#endif
287
Guido van Rossum18468821994-06-20 07:49:28 +0000288/**** Tkapp Object Declaration ****/
289
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300290static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000291
Guido van Rossum00d93061998-05-28 23:06:38 +0000292typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000293 PyObject_HEAD
294 Tcl_Interp *interp;
295 int wantobjects;
296 int threaded; /* True if tcl_platform[threaded] */
297 Tcl_ThreadId thread_id;
298 int dispatching;
299 /* We cannot include tclInt.h, as this is internal.
300 So we cache interesting types here. */
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200301 const Tcl_ObjType *OldBooleanType;
Zachary Ware037605b2014-08-05 11:54:34 -0500302 const Tcl_ObjType *BooleanType;
303 const Tcl_ObjType *ByteArrayType;
304 const Tcl_ObjType *DoubleType;
305 const Tcl_ObjType *IntType;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300306 const Tcl_ObjType *WideIntType;
307 const Tcl_ObjType *BignumType;
Zachary Ware037605b2014-08-05 11:54:34 -0500308 const Tcl_ObjType *ListType;
309 const Tcl_ObjType *ProcBodyType;
310 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000311} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000312
Guido van Rossum18468821994-06-20 07:49:28 +0000313#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000314
Guido van Rossum35d43371997-08-02 00:09:09 +0000315#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000316(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000317
Barry Warsawfa701a81997-01-16 00:15:11 +0000318
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000319
Guido van Rossum18468821994-06-20 07:49:28 +0000320/**** Error Handling ****/
321
322static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000323static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000324static int errorInCmd = 0;
325static PyObject *excInCmd;
326static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000327static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000328
Guilherme Polob681df42009-02-09 22:33:59 +0000329#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000330static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000331#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000332
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000333
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300334static PyObject *Tkapp_UnicodeResult(TkappObject *);
335
Guido van Rossum18468821994-06-20 07:49:28 +0000336static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300337Tkinter_Error(TkappObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +0000338{
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300339 PyObject *res = Tkapp_UnicodeResult(self);
340 if (res != NULL) {
341 PyErr_SetObject(Tkinter_TclError, res);
342 Py_DECREF(res);
343 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000344 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000345}
346
Barry Warsawfa701a81997-01-16 00:15:11 +0000347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000348
Guido van Rossum18468821994-06-20 07:49:28 +0000349/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000350
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000351static int Tkinter_busywaitinterval = 20;
352
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000353#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000354
Guido van Rossum00d93061998-05-28 23:06:38 +0000355/* Millisecond sleep() for Unix platforms. */
356
357static void
Fred Drake509d79a2000-07-08 04:04:38 +0000358Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000359{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000360 /* XXX Too bad if you don't have select(). */
361 struct timeval t;
362 t.tv_sec = milli/1000;
363 t.tv_usec = (milli%1000) * 1000;
364 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000365}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000366#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000367
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000368/* Wait up to 1s for the mainloop to come up. */
369
370static int
371WaitForMainloop(TkappObject* self)
372{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 int i;
374 for (i = 0; i < 10; i++) {
375 if (self->dispatching)
376 return 1;
377 Py_BEGIN_ALLOW_THREADS
378 Sleep(100);
379 Py_END_ALLOW_THREADS
380 }
381 if (self->dispatching)
382 return 1;
383 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
384 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000385}
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000386
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000388
Guido van Rossum18468821994-06-20 07:49:28 +0000389#define ARGSZ 64
390
Barry Warsawfa701a81997-01-16 00:15:11 +0000391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000392
Guido van Rossum18468821994-06-20 07:49:28 +0000393static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200394unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
395{
396 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300397 if (r != NULL || !PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
398 return r;
399 }
400
401 char *buf = NULL;
402 PyErr_Clear();
Serhiy Storchakaa26215d2020-11-15 18:16:59 +0200403 /* Tcl encodes null character as \xc0\x80.
404 https://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8 */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300405 if (memchr(s, '\xc0', size)) {
406 char *q;
407 const char *e = s + size;
408 q = buf = (char *)PyMem_Malloc(size);
409 if (buf == NULL) {
410 PyErr_NoMemory();
411 return NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200412 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300413 while (s != e) {
414 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
415 *q++ = '\0';
416 s += 2;
417 }
418 else
419 *q++ = *s++;
420 }
421 s = buf;
422 size = q - s;
423 }
424 r = PyUnicode_DecodeUTF8(s, size, "surrogateescape");
425 if (buf != NULL) {
426 PyMem_Free(buf);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200427 }
Serhiy Storchakaa26215d2020-11-15 18:16:59 +0200428 if (r == NULL || PyUnicode_KIND(r) == PyUnicode_1BYTE_KIND) {
429 return r;
430 }
431
432 /* In CESU-8 non-BMP characters are represented as a surrogate pair,
433 like in UTF-16, and then each surrogate code point is encoded in UTF-8.
434 https://en.wikipedia.org/wiki/CESU-8 */
435 Py_ssize_t len = PyUnicode_GET_LENGTH(r);
436 Py_ssize_t i, j;
437 /* All encoded surrogate characters start with \xED. */
438 i = PyUnicode_FindChar(r, 0xdcED, 0, len, 1);
439 if (i == -2) {
440 Py_DECREF(r);
441 return NULL;
442 }
443 if (i == -1) {
444 return r;
445 }
446 Py_UCS4 *u = PyUnicode_AsUCS4Copy(r);
447 Py_DECREF(r);
448 if (u == NULL) {
449 return NULL;
450 }
451 Py_UCS4 ch;
452 for (j = i; i < len; i++, u[j++] = ch) {
453 Py_UCS4 ch1, ch2, ch3, high, low;
454 /* Low surrogates U+D800 - U+DBFF are encoded as
455 \xED\xA0\x80 - \xED\xAF\xBF. */
456 ch1 = ch = u[i];
457 if (ch1 != 0xdcED) continue;
458 ch2 = u[i + 1];
459 if (!(0xdcA0 <= ch2 && ch2 <= 0xdcAF)) continue;
460 ch3 = u[i + 2];
461 if (!(0xdc80 <= ch3 && ch3 <= 0xdcBF)) continue;
462 high = 0xD000 | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F);
463 assert(Py_UNICODE_IS_HIGH_SURROGATE(high));
464 /* High surrogates U+DC00 - U+DFFF are encoded as
465 \xED\xB0\x80 - \xED\xBF\xBF. */
466 ch1 = u[i + 3];
467 if (ch1 != 0xdcED) continue;
468 ch2 = u[i + 4];
469 if (!(0xdcB0 <= ch2 && ch2 <= 0xdcBF)) continue;
470 ch3 = u[i + 5];
471 if (!(0xdc80 <= ch3 && ch3 <= 0xdcBF)) continue;
472 low = 0xD000 | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F);
473 assert(Py_UNICODE_IS_HIGH_SURROGATE(high));
474 ch = Py_UNICODE_JOIN_SURROGATES(high, low);
475 i += 5;
476 }
477 r = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, u, j);
478 PyMem_Free(u);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200479 return r;
480}
481
482static PyObject *
483unicodeFromTclString(const char *s)
484{
485 return unicodeFromTclStringAndSize(s, strlen(s));
486}
487
488static PyObject *
489unicodeFromTclObj(Tcl_Obj *value)
490{
491 int len;
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300492#if USE_TCL_UNICODE
493 int byteorder = NATIVE_BYTEORDER;
494 const Tcl_UniChar *u = Tcl_GetUnicodeFromObj(value, &len);
495 if (sizeof(Tcl_UniChar) == 2)
496 return PyUnicode_DecodeUTF16((const char *)u, len * 2,
497 "surrogatepass", &byteorder);
498 else if (sizeof(Tcl_UniChar) == 4)
499 return PyUnicode_DecodeUTF32((const char *)u, len * 4,
500 "surrogatepass", &byteorder);
501 else
502 Py_UNREACHABLE();
503#else
504 const char *s = Tcl_GetStringFromObj(value, &len);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200505 return unicodeFromTclStringAndSize(s, len);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300506#endif
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200507}
508
509
510static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300511Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000512{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300514 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000515 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000517 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300518 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000519 }
Guido van Rossum18468821994-06-20 07:49:28 +0000520
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000521 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
522 /* Not a list.
523 * Could be a quoted string containing funnies, e.g. {"}.
524 * Return the string itself.
525 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200526 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000527 }
Guido van Rossum18468821994-06-20 07:49:28 +0000528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000529 if (argc == 0)
530 v = PyUnicode_FromString("");
531 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200532 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 else if ((v = PyTuple_New(argc)) != NULL) {
534 int i;
535 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000537 for (i = 0; i < argc; i++) {
538 if ((w = Split(argv[i])) == NULL) {
539 Py_DECREF(v);
540 v = NULL;
541 break;
542 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300543 PyTuple_SET_ITEM(v, i, w);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000544 }
545 }
546 Tcl_Free(FREECAST argv);
547 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000548}
549
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300550/* In some cases, Tcl will still return strings that are supposed to
551 be lists. SplitObj walks through a nested tuple, finding string
552 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000553
Martin v. Löwis59683e82008-06-13 07:50:45 +0000554static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000555SplitObj(PyObject *arg)
556{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 if (PyTuple_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200558 Py_ssize_t i, size;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000559 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000560
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300561 size = PyTuple_GET_SIZE(arg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 result = NULL;
563 /* Recursively invoke SplitObj for all tuple items.
564 If this does not return a new object, no action is
565 needed. */
566 for(i = 0; i < size; i++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300567 elem = PyTuple_GET_ITEM(arg, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000568 newelem = SplitObj(elem);
569 if (!newelem) {
570 Py_XDECREF(result);
571 return NULL;
572 }
573 if (!result) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200574 Py_ssize_t k;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000575 if (newelem == elem) {
576 Py_DECREF(newelem);
577 continue;
578 }
579 result = PyTuple_New(size);
580 if (!result)
581 return NULL;
582 for(k = 0; k < i; k++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300583 elem = PyTuple_GET_ITEM(arg, k);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000584 Py_INCREF(elem);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300585 PyTuple_SET_ITEM(result, k, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 }
587 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300588 PyTuple_SET_ITEM(result, i, newelem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000589 }
590 if (result)
591 return result;
592 /* Fall through, returning arg. */
593 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300594 else if (PyList_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200595 Py_ssize_t i, size;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300596 PyObject *elem, *newelem, *result;
597
598 size = PyList_GET_SIZE(arg);
599 result = PyTuple_New(size);
600 if (!result)
601 return NULL;
602 /* Recursively invoke SplitObj for all list items. */
603 for(i = 0; i < size; i++) {
604 elem = PyList_GET_ITEM(arg, i);
605 newelem = SplitObj(elem);
606 if (!newelem) {
607 Py_XDECREF(result);
608 return NULL;
609 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300610 PyTuple_SET_ITEM(result, i, newelem);
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300611 }
612 return result;
613 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300614 else if (PyUnicode_Check(arg)) {
615 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300616 const char **argv;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200617 const char *list = PyUnicode_AsUTF8(arg);
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300618
619 if (list == NULL ||
620 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
621 Py_INCREF(arg);
622 return arg;
623 }
624 Tcl_Free(FREECAST argv);
625 if (argc > 1)
626 return Split(list);
627 /* Fall through, returning arg. */
628 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000629 else if (PyBytes_Check(arg)) {
630 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300631 const char **argv;
Serhiy Storchaka8f87eef2020-04-12 14:58:27 +0300632 const char *list = PyBytes_AS_STRING(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000633
Serhiy Storchaka8f87eef2020-04-12 14:58:27 +0300634 if (Tcl_SplitList((Tcl_Interp *)NULL, (char *)list, &argc, &argv) != TCL_OK) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000635 Py_INCREF(arg);
636 return arg;
637 }
638 Tcl_Free(FREECAST argv);
639 if (argc > 1)
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300640 return Split(PyBytes_AS_STRING(arg));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641 /* Fall through, returning arg. */
642 }
643 Py_INCREF(arg);
644 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000645}
Barry Warsawfa701a81997-01-16 00:15:11 +0000646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +0300648/*[clinic input]
649module _tkinter
650class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec"
651class _tkinter.Tcl_Obj "PyTclObject *" "&PyTclObject_Type_spec"
652class _tkinter.tktimertoken "TkttObject *" "&Tktt_Type_spec"
653[clinic start generated code]*/
654/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b1ebf15c162ee229]*/
655
Guido van Rossum18468821994-06-20 07:49:28 +0000656/**** Tkapp Object ****/
657
658#ifndef WITH_APPINIT
659int
Fred Drake509d79a2000-07-08 04:04:38 +0000660Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000661{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 if (Tcl_Init(interp) == TCL_ERROR) {
665 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
666 return TCL_ERROR;
667 }
Guilherme Polob681df42009-02-09 22:33:59 +0000668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000669 _tkinter_skip_tk_init = Tcl_GetVar(interp,
670 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
671 if (_tkinter_skip_tk_init != NULL &&
672 strcmp(_tkinter_skip_tk_init, "1") == 0) {
673 return TCL_OK;
674 }
Guilherme Polob681df42009-02-09 22:33:59 +0000675
676#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 if (tk_load_failed) {
678 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
679 return TCL_ERROR;
680 }
Guilherme Polob681df42009-02-09 22:33:59 +0000681#endif
682
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000683 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000684#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000686#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
688 return TCL_ERROR;
689 }
Guilherme Polob681df42009-02-09 22:33:59 +0000690
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000692}
693#endif /* !WITH_APPINIT */
694
Guido van Rossum18468821994-06-20 07:49:28 +0000695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000696
Barry Warsawfa701a81997-01-16 00:15:11 +0000697
698/* Initialize the Tk application; see the `main' function in
699 * `tkMain.c'.
700 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000701
Thomas Wouters58d05102000-07-24 14:43:35 +0000702static void EnableEventHook(void); /* Forward */
703static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000704
Barry Warsawfa701a81997-01-16 00:15:11 +0000705static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300706Tkapp_New(const char *screenName, const char *className,
707 int interactive, int wantobjects, int wantTk, int sync,
708 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000709{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000710 TkappObject *v;
711 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000712
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300713 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000714 if (v == NULL)
715 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 v->interp = Tcl_CreateInterp();
718 v->wantobjects = wantobjects;
719 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
720 TCL_GLOBAL_ONLY) != NULL;
721 v->thread_id = Tcl_GetCurrentThread();
722 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000723
724#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000725 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300726 PyErr_SetString(PyExc_RuntimeError,
727 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000728 Py_DECREF(v);
729 return 0;
730 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000731#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000732 if (v->threaded && tcl_lock) {
733 /* If Tcl is threaded, we don't need the lock. */
734 PyThread_free_lock(tcl_lock);
735 tcl_lock = NULL;
736 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000737
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200738 v->OldBooleanType = Tcl_GetObjType("boolean");
739 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000740 v->ByteArrayType = Tcl_GetObjType("bytearray");
741 v->DoubleType = Tcl_GetObjType("double");
742 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300743 v->WideIntType = Tcl_GetObjType("wideInt");
744 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000745 v->ListType = Tcl_GetObjType("list");
746 v->ProcBodyType = Tcl_GetObjType("procbody");
747 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 /* Delete the 'exit' command, which can screw things up */
750 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000751
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752 if (screenName != NULL)
753 Tcl_SetVar2(v->interp, "env", "DISPLAY",
754 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000755
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000756 if (interactive)
757 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
758 else
759 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000760
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000761 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200762 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000763 if (!argv0) {
764 PyErr_NoMemory();
765 Py_DECREF(v);
766 return NULL;
767 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 strcpy(argv0, className);
Jordon Xu2ec70102019-09-11 00:04:08 +0800770 if (Py_ISUPPER(argv0[0]))
771 argv0[0] = Py_TOLOWER(argv0[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000772 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200773 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000774
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 if (! wantTk) {
776 Tcl_SetVar(v->interp,
777 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
778 }
Guilherme Polob681df42009-02-09 22:33:59 +0000779#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000780 else if (tk_load_failed) {
781 Tcl_SetVar(v->interp,
782 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
783 }
Guilherme Polob681df42009-02-09 22:33:59 +0000784#endif
David Aschere2b4b322004-02-18 05:59:53 +0000785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000786 /* some initial arguments need to be in argv */
787 if (sync || use) {
788 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200789 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000790
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000791 if (sync)
792 len += sizeof "-sync";
793 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200794 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000795
Victor Stinneree6c3c72014-09-11 17:50:21 +0200796 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000797 if (!args) {
798 PyErr_NoMemory();
799 Py_DECREF(v);
800 return NULL;
801 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000802
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000803 args[0] = '\0';
804 if (sync)
805 strcat(args, "-sync");
806 if (use) {
807 if (sync)
808 strcat(args, " ");
809 strcat(args, "-use ");
810 strcat(args, use);
811 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000812
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000813 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200814 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000815 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000816
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500817#ifdef MS_WINDOWS
818 {
819 PyObject *str_path;
820 PyObject *utf8_path;
821 DWORD ret;
822
823 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
824 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
825 str_path = _get_tcl_lib_path();
826 if (str_path == NULL && PyErr_Occurred()) {
827 return NULL;
828 }
829 if (str_path != NULL) {
830 utf8_path = PyUnicode_AsUTF8String(str_path);
831 if (utf8_path == NULL) {
832 return NULL;
833 }
834 Tcl_SetVar(v->interp,
835 "tcl_library",
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300836 PyBytes_AS_STRING(utf8_path),
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500837 TCL_GLOBAL_ONLY);
838 Py_DECREF(utf8_path);
839 }
840 }
841 }
842#endif
843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000844 if (Tcl_AppInit(v->interp) != TCL_OK) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300845 PyObject *result = Tkinter_Error(v);
Guilherme Polob681df42009-02-09 22:33:59 +0000846#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000847 if (wantTk) {
848 const char *_tkinter_tk_failed;
849 _tkinter_tk_failed = Tcl_GetVar(v->interp,
850 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000851
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000852 if ( _tkinter_tk_failed != NULL &&
853 strcmp(_tkinter_tk_failed, "1") == 0) {
854 tk_load_failed = 1;
855 }
856 }
Guilherme Polob681df42009-02-09 22:33:59 +0000857#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000858 Py_DECREF((PyObject *)v);
859 return (TkappObject *)result;
860 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000861
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000862 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000863
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000864 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000865}
866
Barry Warsawfa701a81997-01-16 00:15:11 +0000867
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000868static void
869Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000870 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000871{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000872 Py_BEGIN_ALLOW_THREADS;
873 Tcl_MutexLock(mutex);
874 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
875 Tcl_ThreadAlert(self->thread_id);
876 Tcl_ConditionWait(cond, mutex, NULL);
877 Tcl_MutexUnlock(mutex);
878 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000879}
880
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881
Guido van Rossum18468821994-06-20 07:49:28 +0000882/** Tcl Eval **/
883
Martin v. Löwisffad6332002-11-26 09:28:05 +0000884typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000885 PyObject_HEAD
886 Tcl_Obj *value;
887 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000888} PyTclObject;
889
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300890static PyObject *PyTclObject_Type;
Dong-hee Na1b55b652020-02-17 19:09:15 +0900891#define PyTclObject_Check(v) Py_IS_TYPE(v, (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000892
893static PyObject *
894newPyTclObject(Tcl_Obj *arg)
895{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000896 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300897 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000898 if (self == NULL)
899 return NULL;
900 Tcl_IncrRefCount(arg);
901 self->value = arg;
902 self->string = NULL;
903 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000904}
905
906static void
907PyTclObject_dealloc(PyTclObject *self)
908{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200909 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000910 Tcl_DecrRefCount(self->value);
911 Py_XDECREF(self->string);
Victor Stinner32bd68c2020-12-01 10:37:39 +0100912 PyObject_Free(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200913 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000914}
915
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000916/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000917PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000918"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000919
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000920static PyObject *
921PyTclObject_string(PyTclObject *self, void *ignored)
922{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000923 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200924 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000925 if (!self->string)
926 return NULL;
927 }
928 Py_INCREF(self->string);
929 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000930}
931
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000932static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200933PyTclObject_str(PyTclObject *self)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000934{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200935 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000936 Py_INCREF(self->string);
937 return self->string;
938 }
939 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200940 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000941}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000942
Martin v. Löwisffad6332002-11-26 09:28:05 +0000943static PyObject *
944PyTclObject_repr(PyTclObject *self)
945{
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200946 PyObject *repr, *str = PyTclObject_str(self);
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300947 if (str == NULL)
948 return NULL;
949 repr = PyUnicode_FromFormat("<%s object: %R>",
950 self->value->typePtr->name, str);
951 Py_DECREF(str);
952 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000953}
954
Mark Dickinson211c6252009-02-01 10:28:51 +0000955static PyObject *
956PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000957{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000958 int result;
Mark Dickinson211c6252009-02-01 10:28:51 +0000959
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000960 /* neither argument should be NULL, unless something's gone wrong */
961 if (self == NULL || other == NULL) {
962 PyErr_BadInternalCall();
963 return NULL;
964 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000965
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000966 /* both arguments should be instances of PyTclObject */
967 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
stratakise8b19652017-11-02 11:32:54 +0100968 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000969 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000970
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000971 if (self == other)
972 /* fast path when self and other are identical */
973 result = 0;
974 else
975 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
976 Tcl_GetString(((PyTclObject *)other)->value));
stratakise8b19652017-11-02 11:32:54 +0100977 Py_RETURN_RICHCOMPARE(result, 0, op);
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000978}
979
Martin v. Löwis39195712003-01-04 00:33:13 +0000980PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
981
Martin v. Löwisffad6332002-11-26 09:28:05 +0000982static PyObject*
983get_typename(PyTclObject* obj, void* ignored)
984{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200985 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000986}
987
Martin v. Löwis39195712003-01-04 00:33:13 +0000988
Martin v. Löwisffad6332002-11-26 09:28:05 +0000989static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000990 {"typename", (getter)get_typename, NULL, get_typename__doc__},
991 {"string", (getter)PyTclObject_string, NULL,
992 PyTclObject_string__doc__},
993 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000994};
995
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300996static PyType_Slot PyTclObject_Type_slots[] = {
997 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
998 {Py_tp_repr, (reprfunc)PyTclObject_repr},
999 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +02001000 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03001001 {Py_tp_richcompare, PyTclObject_richcompare},
1002 {Py_tp_getset, PyTclObject_getsetlist},
1003 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +00001004};
1005
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03001006static PyType_Spec PyTclObject_Type_spec = {
1007 "_tkinter.Tcl_Obj",
1008 sizeof(PyTclObject),
1009 0,
Victor Stinner3bb09942021-04-30 12:46:15 +02001010 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03001011 PyTclObject_Type_slots,
1012};
1013
1014
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -07001015#if SIZE_MAX > INT_MAX
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001016#define CHECK_STRING_LENGTH(s) do { \
1017 if (s != NULL && strlen(s) >= INT_MAX) { \
1018 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
1019 return NULL; \
1020 } } while(0)
1021#else
1022#define CHECK_STRING_LENGTH(s)
1023#endif
1024
Andrew York003708b2020-05-15 03:43:58 -07001025#ifdef HAVE_LIBTOMMATH
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001026static Tcl_Obj*
1027asBignumObj(PyObject *value)
1028{
1029 Tcl_Obj *result;
1030 int neg;
1031 PyObject *hexstr;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +02001032 const char *hexchars;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001033 mp_int bigValue;
1034
1035 neg = Py_SIZE(value) < 0;
1036 hexstr = _PyLong_Format(value, 16);
1037 if (hexstr == NULL)
1038 return NULL;
1039 hexchars = PyUnicode_AsUTF8(hexstr);
1040 if (hexchars == NULL) {
1041 Py_DECREF(hexstr);
1042 return NULL;
1043 }
1044 hexchars += neg + 2; /* skip sign and "0x" */
1045 mp_init(&bigValue);
1046 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
1047 mp_clear(&bigValue);
1048 Py_DECREF(hexstr);
1049 PyErr_NoMemory();
1050 return NULL;
1051 }
1052 Py_DECREF(hexstr);
1053 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
1054 result = Tcl_NewBignumObj(&bigValue);
1055 mp_clear(&bigValue);
1056 if (result == NULL) {
1057 PyErr_NoMemory();
1058 return NULL;
1059 }
1060 return result;
1061}
1062#endif
1063
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001064static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001065AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001066{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001067 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001068
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001069 if (PyBytes_Check(value)) {
1070 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
1071 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1072 return NULL;
1073 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +03001074 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001075 (int)PyBytes_GET_SIZE(value));
1076 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001077
1078 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001079 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001080
1081 if (PyLong_CheckExact(value)) {
1082 int overflow;
1083 long longValue;
1084#ifdef TCL_WIDE_INT_TYPE
1085 Tcl_WideInt wideValue;
1086#endif
1087 longValue = PyLong_AsLongAndOverflow(value, &overflow);
1088 if (!overflow) {
1089 return Tcl_NewLongObj(longValue);
1090 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001091 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001092 fall through to wideInt handling. */
1093#ifdef TCL_WIDE_INT_TYPE
1094 if (_PyLong_AsByteArray((PyLongObject *)value,
1095 (unsigned char *)(void *)&wideValue,
1096 sizeof(wideValue),
1097 PY_LITTLE_ENDIAN,
1098 /* signed */ 1) == 0) {
1099 return Tcl_NewWideIntObj(wideValue);
1100 }
1101 PyErr_Clear();
1102#endif
1103 /* If there is an overflow in the wideInt conversion,
1104 fall through to bignum handling. */
Andrew York003708b2020-05-15 03:43:58 -07001105#ifdef HAVE_LIBTOMMATH
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001106 return asBignumObj(value);
1107#endif
1108 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001109 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001110 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001111
1112 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001113 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001114
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +03001115 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001116 Tcl_Obj **argv;
1117 Py_ssize_t size, i;
1118
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001119 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001120 if (size == 0)
1121 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001122 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001123 PyErr_SetString(PyExc_OverflowError,
1124 PyTuple_Check(value) ? "tuple is too long" :
1125 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001126 return NULL;
1127 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001128 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
1129 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001130 PyErr_NoMemory();
1131 return NULL;
1132 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001133 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001134 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001135 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001136 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001137 return result;
1138 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001139
1140 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001141 if (PyUnicode_READY(value) == -1)
1142 return NULL;
1143
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001144 Py_ssize_t size = PyUnicode_GET_LENGTH(value);
1145 if (size == 0) {
1146 return Tcl_NewStringObj("", 0);
1147 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001148 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1149 PyErr_SetString(PyExc_OverflowError, "string is too long");
1150 return NULL;
1151 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001152 if (PyUnicode_IS_ASCII(value)) {
1153 return Tcl_NewStringObj((const char *)PyUnicode_DATA(value),
1154 (int)size);
1155 }
1156
1157 PyObject *encoded;
1158#if USE_TCL_UNICODE
1159 if (sizeof(Tcl_UniChar) == 2)
1160 encoded = _PyUnicode_EncodeUTF16(value,
1161 "surrogatepass", NATIVE_BYTEORDER);
1162 else if (sizeof(Tcl_UniChar) == 4)
1163 encoded = _PyUnicode_EncodeUTF32(value,
1164 "surrogatepass", NATIVE_BYTEORDER);
1165 else
1166 Py_UNREACHABLE();
1167#else
1168 encoded = _PyUnicode_AsUTF8String(value, "surrogateescape");
1169#endif
1170 if (!encoded) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001171 return NULL;
1172 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001173 size = PyBytes_GET_SIZE(encoded);
1174 if (size > INT_MAX) {
1175 Py_DECREF(encoded);
1176 PyErr_SetString(PyExc_OverflowError, "string is too long");
1177 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001178 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001179#if USE_TCL_UNICODE
1180 result = Tcl_NewUnicodeObj((const Tcl_UniChar *)PyBytes_AS_STRING(encoded),
1181 (int)(size / sizeof(Tcl_UniChar)));
1182#else
1183 result = Tcl_NewStringObj(PyBytes_AS_STRING(encoded), (int)size);
1184#endif
1185 Py_DECREF(encoded);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001186 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001187 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001188
1189 if (PyTclObject_Check(value)) {
Serhiy Storchakadf13df42018-10-23 22:40:54 +03001190 return ((PyTclObject*)value)->value;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001191 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001192
1193 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001194 PyObject *v = PyObject_Str(value);
1195 if (!v)
1196 return 0;
1197 result = AsObj(v);
1198 Py_DECREF(v);
1199 return result;
1200 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001201}
1202
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001203static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001204fromBoolean(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001205{
1206 int boolValue;
1207 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1208 return Tkinter_Error(tkapp);
1209 return PyBool_FromLong(boolValue);
1210}
1211
Martin v. Löwisffad6332002-11-26 09:28:05 +00001212static PyObject*
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001213fromWideIntObj(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001214{
1215 Tcl_WideInt wideValue;
1216 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001217 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1218 return PyLong_FromLongLong(wideValue);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001219 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1220 sizeof(wideValue),
1221 PY_LITTLE_ENDIAN,
1222 /* signed */ 1);
1223 }
1224 return NULL;
1225}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001226
Andrew York003708b2020-05-15 03:43:58 -07001227#ifdef HAVE_LIBTOMMATH
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001228static PyObject*
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001229fromBignumObj(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001230{
1231 mp_int bigValue;
1232 unsigned long numBytes;
1233 unsigned char *bytes;
1234 PyObject *res;
1235
1236 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1237 return Tkinter_Error(tkapp);
1238 numBytes = mp_unsigned_bin_size(&bigValue);
1239 bytes = PyMem_Malloc(numBytes);
1240 if (bytes == NULL) {
1241 mp_clear(&bigValue);
1242 return PyErr_NoMemory();
1243 }
1244 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1245 &numBytes) != MP_OKAY) {
1246 mp_clear(&bigValue);
1247 PyMem_Free(bytes);
1248 return PyErr_NoMemory();
1249 }
1250 res = _PyLong_FromByteArray(bytes, numBytes,
1251 /* big-endian */ 0,
1252 /* unsigned */ 0);
1253 PyMem_Free(bytes);
1254 if (res != NULL && bigValue.sign == MP_NEG) {
1255 PyObject *res2 = PyNumber_Negative(res);
1256 Py_DECREF(res);
1257 res = res2;
1258 }
1259 mp_clear(&bigValue);
1260 return res;
1261}
1262#endif
1263
Martin v. Löwisffad6332002-11-26 09:28:05 +00001264static PyObject*
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001265FromObj(TkappObject *tkapp, Tcl_Obj *value)
Martin v. Löwisffad6332002-11-26 09:28:05 +00001266{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001267 PyObject *result = NULL;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001268 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001270 if (value->typePtr == NULL) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001271 return unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001272 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001273
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001274 if (value->typePtr == tkapp->BooleanType ||
1275 value->typePtr == tkapp->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001276 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001277 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001278
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001279 if (value->typePtr == tkapp->ByteArrayType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001280 int size;
1281 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1282 return PyBytes_FromStringAndSize(data, size);
1283 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001284
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001285 if (value->typePtr == tkapp->DoubleType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001286 return PyFloat_FromDouble(value->internalRep.doubleValue);
1287 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001288
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001289 if (value->typePtr == tkapp->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001290 long longValue;
1291 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1292 return PyLong_FromLong(longValue);
1293 /* If there is an error in the long conversion,
1294 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001295 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001296
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001297 if (value->typePtr == tkapp->IntType ||
1298 value->typePtr == tkapp->WideIntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001299 result = fromWideIntObj(tkapp, value);
1300 if (result != NULL || PyErr_Occurred())
1301 return result;
1302 Tcl_ResetResult(interp);
1303 /* If there is an error in the wideInt conversion,
1304 fall through to bignum handling. */
1305 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001306
Andrew York003708b2020-05-15 03:43:58 -07001307#ifdef HAVE_LIBTOMMATH
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001308 if (value->typePtr == tkapp->IntType ||
1309 value->typePtr == tkapp->WideIntType ||
1310 value->typePtr == tkapp->BignumType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001311 return fromBignumObj(tkapp, value);
1312 }
1313#endif
1314
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001315 if (value->typePtr == tkapp->ListType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001316 int size;
1317 int i, status;
1318 PyObject *elem;
1319 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001320
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001321 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001322 if (status == TCL_ERROR)
1323 return Tkinter_Error(tkapp);
1324 result = PyTuple_New(size);
1325 if (!result)
1326 return NULL;
1327 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001328 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001329 if (status == TCL_ERROR) {
1330 Py_DECREF(result);
1331 return Tkinter_Error(tkapp);
1332 }
1333 elem = FromObj(tkapp, tcl_elem);
1334 if (!elem) {
1335 Py_DECREF(result);
1336 return NULL;
1337 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001338 PyTuple_SET_ITEM(result, i, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001339 }
1340 return result;
1341 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001342
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001343 if (value->typePtr == tkapp->ProcBodyType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001344 /* fall through: return tcl object. */
1345 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001346
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001347 if (value->typePtr == tkapp->StringType) {
1348 return unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001349 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001350
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001351#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001352 if (tkapp->BooleanType == NULL &&
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001353 strcmp(value->typePtr->name, "booleanString") == 0) {
1354 /* booleanString type is not registered in Tcl */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001355 tkapp->BooleanType = value->typePtr;
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001356 return fromBoolean(tkapp, value);
1357 }
1358#endif
1359
Andrew York003708b2020-05-15 03:43:58 -07001360#ifdef HAVE_LIBTOMMATH
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001361 if (tkapp->BignumType == NULL &&
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001362 strcmp(value->typePtr->name, "bignum") == 0) {
1363 /* bignum type is not registered in Tcl */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001364 tkapp->BignumType = value->typePtr;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001365 return fromBignumObj(tkapp, value);
1366 }
1367#endif
1368
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001369 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001370}
1371
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001372/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001373TCL_DECLARE_MUTEX(call_mutex)
1374
1375typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001376 Tcl_Event ev; /* Must be first */
1377 TkappObject *self;
1378 PyObject *args;
1379 int flags;
1380 PyObject **res;
1381 PyObject **exc_type, **exc_value, **exc_tb;
1382 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001383} Tkapp_CallEvent;
1384
1385void
1386Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001387{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001388 int i;
1389 for (i = 0; i < objc; i++)
1390 Tcl_DecrRefCount(objv[i]);
1391 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001392 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001393}
Guido van Rossum18468821994-06-20 07:49:28 +00001394
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001395/* Convert Python objects to Tcl objects. This must happen in the
1396 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001397
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001398static Tcl_Obj**
1399Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1400{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001401 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001402 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001403 if (args == NULL)
1404 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001405
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001406 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001407 objv[0] = AsObj(args);
Serhiy Storchaka0b3ec192017-03-23 17:53:47 +02001408 if (objv[0] == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001409 goto finally;
1410 objc = 1;
1411 Tcl_IncrRefCount(objv[0]);
1412 }
1413 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001414 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001415
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001416 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001417 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001418 PyErr_SetString(PyExc_OverflowError,
1419 PyTuple_Check(args) ? "tuple is too long" :
1420 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001421 return NULL;
1422 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001423 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001424 if (objv == NULL) {
1425 PyErr_NoMemory();
1426 objc = 0;
1427 goto finally;
1428 }
1429 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001430
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001431 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001432 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001433 if (v == Py_None) {
1434 objc = i;
1435 break;
1436 }
1437 objv[i] = AsObj(v);
1438 if (!objv[i]) {
1439 /* Reset objc, so it attempts to clear
1440 objects only up to i. */
1441 objc = i;
1442 goto finally;
1443 }
1444 Tcl_IncrRefCount(objv[i]);
1445 }
1446 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001447 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001448 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001449finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001450 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001451 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001452}
Guido van Rossum212643f1998-04-29 16:22:14 +00001453
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001454/* Convert the results of a command call into a Python string. */
1455
1456static PyObject *
1457Tkapp_UnicodeResult(TkappObject *self)
1458{
1459 return unicodeFromTclObj(Tcl_GetObjResult(self->interp));
1460}
1461
1462
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001463/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001464
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001465static PyObject *
1466Tkapp_ObjectResult(TkappObject *self)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001467{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001468 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001469 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001470 if (self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001471 /* Not sure whether the IncrRef is necessary, but something
1472 may overwrite the interpreter result while we are
1473 converting it. */
1474 Tcl_IncrRefCount(value);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001475 res = FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001476 Tcl_DecrRefCount(value);
1477 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001478 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001479 }
1480 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001481}
Guido van Rossum632de272000-03-29 00:19:50 +00001482
Benjamin Peterson5879d412009-03-30 14:51:56 +00001483
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001484/* Tkapp_CallProc is the event procedure that is executed in the context of
1485 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1486 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001487
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001488static int
1489Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1490{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001491 Tcl_Obj *objStore[ARGSZ];
1492 Tcl_Obj **objv;
1493 int objc;
1494 int i;
1495 ENTER_PYTHON
1496 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1497 if (!objv) {
1498 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1499 *(e->res) = NULL;
1500 }
1501 LEAVE_PYTHON
1502 if (!objv)
1503 goto done;
1504 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1505 ENTER_PYTHON
1506 if (i == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001507 *(e->res) = Tkinter_Error(e->self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001508 }
1509 else {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001510 *(e->res) = Tkapp_ObjectResult(e->self);
1511 }
1512 if (*(e->res) == NULL) {
1513 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001514 }
1515 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001517 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001518done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001519 /* Wake up calling thread. */
1520 Tcl_MutexLock(&call_mutex);
1521 Tcl_ConditionNotify(e->done);
1522 Tcl_MutexUnlock(&call_mutex);
1523 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001524}
1525
Benjamin Peterson5879d412009-03-30 14:51:56 +00001526
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001527/* This is the main entry point for calling a Tcl command.
1528 It supports three cases, with regard to threading:
1529 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1530 the context of the calling thread.
1531 2. Tcl is threaded, caller of the command is in the interpreter thread:
1532 Execute the command in the calling thread. Since the Tcl lock will
1533 not be used, we can merge that with case 1.
1534 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1535 the interpreter thread. Allocation of Tcl objects needs to occur in the
1536 interpreter thread, so we ship the PyObject* args to the target thread,
1537 and perform processing there. */
1538
1539static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001540Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001541{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001542 Tcl_Obj *objStore[ARGSZ];
1543 Tcl_Obj **objv = NULL;
1544 int objc, i;
1545 PyObject *res = NULL;
1546 TkappObject *self = (TkappObject*)selfptr;
1547 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001548
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001549 /* If args is a single tuple, replace with contents of tuple */
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001550 if (PyTuple_GET_SIZE(args) == 1) {
1551 PyObject *item = PyTuple_GET_ITEM(args, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001552 if (PyTuple_Check(item))
1553 args = item;
1554 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001555 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1556 /* We cannot call the command directly. Instead, we must
1557 marshal the parameters to the interpreter thread. */
1558 Tkapp_CallEvent *ev;
1559 Tcl_Condition cond = NULL;
1560 PyObject *exc_type, *exc_value, *exc_tb;
1561 if (!WaitForMainloop(self))
1562 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001563 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1564 if (ev == NULL) {
1565 PyErr_NoMemory();
1566 return NULL;
1567 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1569 ev->self = self;
1570 ev->args = args;
1571 ev->res = &res;
1572 ev->exc_type = &exc_type;
1573 ev->exc_value = &exc_value;
1574 ev->exc_tb = &exc_tb;
1575 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001576
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001577 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001579 if (res == NULL) {
1580 if (exc_type)
1581 PyErr_Restore(exc_type, exc_value, exc_tb);
1582 else
1583 PyErr_SetObject(Tkinter_TclError, exc_value);
1584 }
1585 Tcl_ConditionFinalize(&cond);
1586 }
1587 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001588 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001589
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001590 objv = Tkapp_CallArgs(args, objStore, &objc);
1591 if (!objv)
1592 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001593
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001594 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001595
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001596 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001598 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001600 if (i == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001601 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001602 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001603 res = Tkapp_ObjectResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001605 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001607 Tkapp_CallDeallocArgs(objv, objStore, objc);
1608 }
1609 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001610}
1611
1612
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001613/*[clinic input]
1614_tkinter.tkapp.eval
1615
1616 script: str
1617 /
1618
1619[clinic start generated code]*/
1620
Barry Warsawfa701a81997-01-16 00:15:11 +00001621static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001622_tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1623/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001624{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001625 PyObject *res = NULL;
1626 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001627
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001628 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001629 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001631 ENTER_TCL
1632 err = Tcl_Eval(Tkapp_Interp(self), script);
1633 ENTER_OVERLAP
1634 if (err == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001635 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001636 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001637 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001638 LEAVE_OVERLAP_TCL
1639 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001640}
1641
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001642/*[clinic input]
1643_tkinter.tkapp.evalfile
1644
1645 fileName: str
1646 /
1647
1648[clinic start generated code]*/
1649
Guido van Rossum18468821994-06-20 07:49:28 +00001650static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001651_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1652/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001653{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001654 PyObject *res = NULL;
1655 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001656
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001657 CHECK_STRING_LENGTH(fileName);
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 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1662 ENTER_OVERLAP
1663 if (err == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001664 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001665 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001666 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001667 LEAVE_OVERLAP_TCL
1668 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001669}
1670
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001671/*[clinic input]
1672_tkinter.tkapp.record
1673
1674 script: str
1675 /
1676
1677[clinic start generated code]*/
1678
Guido van Rossum18468821994-06-20 07:49:28 +00001679static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001680_tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1681/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001682{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001683 PyObject *res = NULL;
1684 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001685
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001686 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001687 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001688
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001689 ENTER_TCL
1690 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1691 ENTER_OVERLAP
1692 if (err == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001693 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001694 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001695 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001696 LEAVE_OVERLAP_TCL
1697 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001698}
1699
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001700/*[clinic input]
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001701_tkinter.tkapp.adderrorinfo
Guido van Rossum18468821994-06-20 07:49:28 +00001702
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001703 msg: str
1704 /
1705
1706[clinic start generated code]*/
1707
1708static PyObject *
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001709_tkinter_tkapp_adderrorinfo_impl(TkappObject *self, const char *msg)
1710/*[clinic end generated code: output=52162eaca2ee53cb input=f4b37aec7c7e8c77]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001711{
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001712 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001713 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001714
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001715 ENTER_TCL
1716 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1717 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001718
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001719 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001720}
1721
Barry Warsawfa701a81997-01-16 00:15:11 +00001722
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001723
Guido van Rossum18468821994-06-20 07:49:28 +00001724/** Tcl Variable **/
1725
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001726typedef PyObject* (*EventFunc)(TkappObject *, PyObject *, int);
Benjamin Peterson5879d412009-03-30 14:51:56 +00001727
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001728TCL_DECLARE_MUTEX(var_mutex)
1729
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001730typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001731 Tcl_Event ev; /* must be first */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001732 TkappObject *self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001733 PyObject *args;
1734 int flags;
1735 EventFunc func;
1736 PyObject **res;
1737 PyObject **exc_type;
1738 PyObject **exc_val;
1739 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001740} VarEvent;
1741
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001742/*[python]
1743
1744class varname_converter(CConverter):
1745 type = 'const char *'
1746 converter = 'varname_converter'
1747
1748[python]*/
1749/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1750
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001751static int
1752varname_converter(PyObject *in, void *_out)
1753{
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +02001754 const char *s;
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001755 const char **out = (const char**)_out;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001756 if (PyBytes_Check(in)) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001757 if (PyBytes_GET_SIZE(in) > INT_MAX) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001758 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1759 return 0;
1760 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001761 s = PyBytes_AS_STRING(in);
1762 if (strlen(s) != (size_t)PyBytes_GET_SIZE(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001763 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001764 return 0;
1765 }
1766 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001767 return 1;
1768 }
1769 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001770 Py_ssize_t size;
1771 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001772 if (s == NULL) {
1773 return 0;
1774 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001775 if (size > INT_MAX) {
1776 PyErr_SetString(PyExc_OverflowError, "string is too long");
1777 return 0;
1778 }
Victor Stinner706768c2014-08-16 01:03:39 +02001779 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001780 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001781 return 0;
1782 }
1783 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001784 return 1;
1785 }
1786 if (PyTclObject_Check(in)) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001787 *out = Tcl_GetString(((PyTclObject *)in)->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001788 return 1;
1789 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001790 PyErr_Format(PyExc_TypeError,
1791 "must be str, bytes or Tcl_Obj, not %.50s",
Victor Stinnerdaa97562020-02-07 03:37:06 +01001792 Py_TYPE(in)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001793 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001794}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001795
Benjamin Peterson5879d412009-03-30 14:51:56 +00001796
Martin v. Löwis59683e82008-06-13 07:50:45 +00001797static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001798var_perform(VarEvent *ev)
1799{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001800 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1801 if (!*(ev->res)) {
1802 PyObject *exc, *val, *tb;
1803 PyErr_Fetch(&exc, &val, &tb);
1804 PyErr_NormalizeException(&exc, &val, &tb);
1805 *(ev->exc_type) = exc;
1806 *(ev->exc_val) = val;
Serhiy Storchaka3ec5f422016-10-28 12:14:34 +03001807 Py_XDECREF(tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001808 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001809
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001810}
1811
1812static int
1813var_proc(VarEvent* ev, int flags)
1814{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001815 ENTER_PYTHON
1816 var_perform(ev);
1817 Tcl_MutexLock(&var_mutex);
1818 Tcl_ConditionNotify(ev->cond);
1819 Tcl_MutexUnlock(&var_mutex);
1820 LEAVE_PYTHON
1821 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001822}
1823
Benjamin Peterson5879d412009-03-30 14:51:56 +00001824
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001825static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001826var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001827{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001828 TkappObject *self = (TkappObject*)selfptr;
1829 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001830 VarEvent *ev;
1831 PyObject *res, *exc_type, *exc_val;
1832 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001833
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001834 /* The current thread is not the interpreter thread. Marshal
1835 the call to the interpreter thread, then wait for
1836 completion. */
1837 if (!WaitForMainloop(self))
1838 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001839
Serhiy Storchaka07940882014-09-11 10:38:54 +03001840 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1841 if (ev == NULL) {
1842 PyErr_NoMemory();
1843 return NULL;
1844 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001845 ev->self = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001846 ev->args = args;
1847 ev->flags = flags;
1848 ev->func = func;
1849 ev->res = &res;
1850 ev->exc_type = &exc_type;
1851 ev->exc_val = &exc_val;
1852 ev->cond = &cond;
1853 ev->ev.proc = (Tcl_EventProc*)var_proc;
1854 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1855 Tcl_ConditionFinalize(&cond);
1856 if (!res) {
1857 PyErr_SetObject(exc_type, exc_val);
1858 Py_DECREF(exc_type);
1859 Py_DECREF(exc_val);
1860 return NULL;
1861 }
1862 return res;
1863 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001864 /* Tcl is not threaded, or this is the interpreter thread. */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001865 return func(self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001866}
1867
Guido van Rossum18468821994-06-20 07:49:28 +00001868static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001869SetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001870{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001871 const char *name1, *name2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001872 PyObject *newValue;
1873 PyObject *res = NULL;
1874 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001875
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001876 switch (PyTuple_GET_SIZE(args)) {
1877 case 2:
1878 if (!PyArg_ParseTuple(args, "O&O:setvar",
1879 varname_converter, &name1, &newValue))
1880 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001881 /* XXX Acquire tcl lock??? */
1882 newval = AsObj(newValue);
1883 if (newval == NULL)
1884 return NULL;
1885 ENTER_TCL
1886 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1887 newval, flags);
1888 ENTER_OVERLAP
1889 if (!ok)
1890 Tkinter_Error(self);
1891 else {
1892 res = Py_None;
1893 Py_INCREF(res);
1894 }
1895 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001896 break;
1897 case 3:
1898 if (!PyArg_ParseTuple(args, "ssO:setvar",
1899 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001900 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001901 CHECK_STRING_LENGTH(name1);
1902 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001903 /* XXX must hold tcl lock already??? */
1904 newval = AsObj(newValue);
1905 ENTER_TCL
1906 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1907 ENTER_OVERLAP
1908 if (!ok)
1909 Tkinter_Error(self);
1910 else {
1911 res = Py_None;
1912 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001913 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001914 LEAVE_OVERLAP_TCL
1915 break;
1916 default:
1917 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1918 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001919 }
1920 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001921}
1922
1923static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001924Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001925{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001926 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001927}
1928
1929static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001930Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001931{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001932 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001933}
1934
Barry Warsawfa701a81997-01-16 00:15:11 +00001935
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001936
Guido van Rossum18468821994-06-20 07:49:28 +00001937static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001938GetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001939{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001940 const char *name1, *name2=NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001941 PyObject *res = NULL;
1942 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001943
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001944 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1945 varname_converter, &name1, &name2))
1946 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001947
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001948 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001949 ENTER_TCL
1950 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1951 ENTER_OVERLAP
1952 if (tres == NULL) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001953 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001954 } else {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001955 if (self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001956 res = FromObj(self, tres);
1957 }
1958 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001959 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001960 }
1961 }
1962 LEAVE_OVERLAP_TCL
1963 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001964}
1965
1966static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001967Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001968{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001969 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001970}
1971
1972static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001973Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001974{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001975 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001976}
1977
Barry Warsawfa701a81997-01-16 00:15:11 +00001978
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001979
Guido van Rossum18468821994-06-20 07:49:28 +00001980static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001981UnsetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001982{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001983 char *name1, *name2=NULL;
1984 int code;
1985 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001986
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001987 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1988 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001989
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001990 CHECK_STRING_LENGTH(name1);
1991 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001992 ENTER_TCL
1993 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1994 ENTER_OVERLAP
1995 if (code == TCL_ERROR)
1996 res = Tkinter_Error(self);
1997 else {
1998 Py_INCREF(Py_None);
1999 res = Py_None;
2000 }
2001 LEAVE_OVERLAP_TCL
2002 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002003}
2004
2005static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002006Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002007{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002008 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00002009}
2010
2011static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002012Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002013{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002014 return var_invoke(UnsetVar, self, args,
2015 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00002016}
2017
Barry Warsawfa701a81997-01-16 00:15:11 +00002018
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002019
Guido van Rossum18468821994-06-20 07:49:28 +00002020/** Tcl to Python **/
2021
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002022/*[clinic input]
2023_tkinter.tkapp.getint
2024
2025 arg: object
2026 /
2027
2028[clinic start generated code]*/
2029
Guido van Rossum18468821994-06-20 07:49:28 +00002030static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002031_tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
2032/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002033{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002034 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002035 Tcl_Obj *value;
2036 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00002037
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002038 if (PyLong_Check(arg)) {
2039 Py_INCREF(arg);
2040 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002041 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002042
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002043 if (PyTclObject_Check(arg)) {
2044 value = ((PyTclObject*)arg)->value;
2045 Tcl_IncrRefCount(value);
2046 }
2047 else {
2048 if (!PyArg_Parse(arg, "s:getint", &s))
2049 return NULL;
2050 CHECK_STRING_LENGTH(s);
2051 value = Tcl_NewStringObj(s, -1);
2052 if (value == NULL)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002053 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002054 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002055 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
2056 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
2057
2058 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
2059 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
2060 */
Andrew York003708b2020-05-15 03:43:58 -07002061#ifdef HAVE_LIBTOMMATH
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002062 result = fromBignumObj(self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002063#else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002064 result = fromWideIntObj(self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002065#endif
2066 Tcl_DecrRefCount(value);
2067 if (result != NULL || PyErr_Occurred())
2068 return result;
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002069 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00002070}
2071
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002072/*[clinic input]
2073_tkinter.tkapp.getdouble
2074
2075 arg: object
2076 /
2077
2078[clinic start generated code]*/
2079
Guido van Rossum18468821994-06-20 07:49:28 +00002080static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002081_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
2082/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002083{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002084 char *s;
2085 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00002086
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002087 if (PyFloat_Check(arg)) {
2088 Py_INCREF(arg);
2089 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002090 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002091
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002092 if (PyNumber_Check(arg)) {
2093 return PyNumber_Float(arg);
2094 }
2095
2096 if (PyTclObject_Check(arg)) {
2097 if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
2098 ((PyTclObject*)arg)->value,
2099 &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002100 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002101 return PyFloat_FromDouble(v);
2102 }
2103
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002104 if (!PyArg_Parse(arg, "s:getdouble", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002105 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002106 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002107 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002108 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002109 return PyFloat_FromDouble(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002110}
2111
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002112/*[clinic input]
2113_tkinter.tkapp.getboolean
2114
2115 arg: object
2116 /
2117
2118[clinic start generated code]*/
2119
Guido van Rossum18468821994-06-20 07:49:28 +00002120static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002121_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
2122/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002123{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002124 char *s;
2125 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002126
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002127 if (PyLong_Check(arg)) { /* int or bool */
2128 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002129 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002130
2131 if (PyTclObject_Check(arg)) {
2132 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2133 ((PyTclObject*)arg)->value,
2134 &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002135 return Tkinter_Error(self);
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002136 return PyBool_FromLong(v);
2137 }
2138
2139 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002140 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002141 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002143 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002144 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002145}
2146
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002147/*[clinic input]
2148_tkinter.tkapp.exprstring
2149
2150 s: str
2151 /
2152
2153[clinic start generated code]*/
2154
Guido van Rossum18468821994-06-20 07:49:28 +00002155static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002156_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2157/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002158{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002159 PyObject *res = NULL;
2160 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002161
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002162 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002163 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002164
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002165 ENTER_TCL
2166 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2167 ENTER_OVERLAP
2168 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002169 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002170 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002171 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002172 LEAVE_OVERLAP_TCL
2173 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002174}
2175
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002176/*[clinic input]
2177_tkinter.tkapp.exprlong
2178
2179 s: str
2180 /
2181
2182[clinic start generated code]*/
2183
Guido van Rossum18468821994-06-20 07:49:28 +00002184static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002185_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2186/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002187{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002188 PyObject *res = NULL;
2189 int retval;
2190 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002191
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002192 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002193 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002195 ENTER_TCL
2196 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2197 ENTER_OVERLAP
2198 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002199 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002200 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002201 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002202 LEAVE_OVERLAP_TCL
2203 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002204}
2205
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002206/*[clinic input]
2207_tkinter.tkapp.exprdouble
2208
2209 s: str
2210 /
2211
2212[clinic start generated code]*/
2213
Guido van Rossum18468821994-06-20 07:49:28 +00002214static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002215_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2216/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002217{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002218 PyObject *res = NULL;
2219 double v;
2220 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002221
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002222 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002223 CHECK_TCL_APPARTMENT;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002224 ENTER_TCL
2225 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2226 ENTER_OVERLAP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002227 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002228 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002229 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002230 res = PyFloat_FromDouble(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002231 LEAVE_OVERLAP_TCL
2232 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002233}
2234
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002235/*[clinic input]
2236_tkinter.tkapp.exprboolean
2237
2238 s: str
2239 /
2240
2241[clinic start generated code]*/
2242
Guido van Rossum18468821994-06-20 07:49:28 +00002243static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002244_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2245/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002246{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002247 PyObject *res = NULL;
2248 int retval;
2249 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002250
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002251 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002252 CHECK_TCL_APPARTMENT;
2253 ENTER_TCL
2254 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2255 ENTER_OVERLAP
2256 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002257 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002258 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002259 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002260 LEAVE_OVERLAP_TCL
2261 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002262}
2263
Barry Warsawfa701a81997-01-16 00:15:11 +00002264
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002265
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002266/*[clinic input]
2267_tkinter.tkapp.splitlist
2268
2269 arg: object
2270 /
2271
2272[clinic start generated code]*/
2273
Guido van Rossum18468821994-06-20 07:49:28 +00002274static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002275_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2276/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002277{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002278 char *list;
2279 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002280 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002281 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002282 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002283
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002284 if (PyTclObject_Check(arg)) {
2285 int objc;
2286 Tcl_Obj **objv;
2287 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2288 ((PyTclObject*)arg)->value,
2289 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002290 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002291 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002292 if (!(v = PyTuple_New(objc)))
2293 return NULL;
2294 for (i = 0; i < objc; i++) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002295 PyObject *s = FromObj(self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002296 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002297 Py_DECREF(v);
2298 return NULL;
2299 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002300 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002301 }
2302 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002303 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002304 if (PyTuple_Check(arg)) {
2305 Py_INCREF(arg);
2306 return arg;
2307 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002308 if (PyList_Check(arg)) {
2309 return PySequence_Tuple(arg);
2310 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002311
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002312 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002313 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002314
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002315 if (strlen(list) >= INT_MAX) {
2316 PyErr_SetString(PyExc_OverflowError, "string is too long");
2317 PyMem_Free(list);
2318 return NULL;
2319 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002320 if (Tcl_SplitList(Tkapp_Interp(self), list,
2321 &argc, &argv) == TCL_ERROR) {
2322 PyMem_Free(list);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002323 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002324 }
Guido van Rossum18468821994-06-20 07:49:28 +00002325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002326 if (!(v = PyTuple_New(argc)))
2327 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002328
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002329 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002330 PyObject *s = unicodeFromTclString(argv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002331 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002332 Py_DECREF(v);
2333 v = NULL;
2334 goto finally;
2335 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002336 PyTuple_SET_ITEM(v, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002337 }
Guido van Rossum18468821994-06-20 07:49:28 +00002338
Barry Warsawfa701a81997-01-16 00:15:11 +00002339 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002340 ckfree(FREECAST argv);
2341 PyMem_Free(list);
2342 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002343}
2344
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002345/*[clinic input]
2346_tkinter.tkapp.split
2347
2348 arg: object
2349 /
2350
2351[clinic start generated code]*/
2352
Guido van Rossum18468821994-06-20 07:49:28 +00002353static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002354_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2355/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002356{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002357 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002358 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002359
Serhiy Storchakad05b0002019-10-08 14:31:35 +03002360 if (PyErr_WarnEx(PyExc_DeprecationWarning,
2361 "split() is deprecated; consider using splitlist() instead", 1))
2362 {
2363 return NULL;
2364 }
2365
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002366 if (PyTclObject_Check(arg)) {
2367 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2368 int objc;
2369 Tcl_Obj **objv;
2370 int i;
2371 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2372 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002373 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002374 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002375 if (objc == 0)
2376 return PyUnicode_FromString("");
2377 if (objc == 1)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002378 return FromObj(self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002379 if (!(v = PyTuple_New(objc)))
2380 return NULL;
2381 for (i = 0; i < objc; i++) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002382 PyObject *s = FromObj(self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002383 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002384 Py_DECREF(v);
2385 return NULL;
2386 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002387 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002388 }
2389 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002390 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002391 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002392 return SplitObj(arg);
2393
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002394 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002395 return NULL;
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002396 if (strlen(list) >= INT_MAX) {
2397 PyErr_SetString(PyExc_OverflowError, "string is too long");
2398 PyMem_Free(list);
2399 return NULL;
2400 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002401 v = Split(list);
2402 PyMem_Free(list);
2403 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002404}
2405
Barry Warsawfa701a81997-01-16 00:15:11 +00002406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407
Guido van Rossum18468821994-06-20 07:49:28 +00002408/** Tcl Command **/
2409
Guido van Rossum00d93061998-05-28 23:06:38 +00002410/* Client data struct */
2411typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002412 PyObject *self;
2413 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002414} PythonCmd_ClientData;
2415
2416static int
Fred Drake509d79a2000-07-08 04:04:38 +00002417PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002418{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002419 errorInCmd = 1;
2420 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2421 LEAVE_PYTHON
2422 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002423}
2424
Guido van Rossum18468821994-06-20 07:49:28 +00002425/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002426 * function or method.
2427 */
Guido van Rossum18468821994-06-20 07:49:28 +00002428static int
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002429PythonCmd(ClientData clientData, Tcl_Interp *interp,
2430 int objc, Tcl_Obj *const objv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002431{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002432 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002433 PyObject *args, *res;
2434 int i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002435 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002436
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002437 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002438
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002439 /* Create argument tuple (objv1, ..., objvN) */
2440 if (!(args = PyTuple_New(objc - 1)))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002441 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002442
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002443 for (i = 0; i < (objc - 1); i++) {
2444 PyObject *s = unicodeFromTclObj(objv[i + 1]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002445 if (!s) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002446 Py_DECREF(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002447 return PythonCmd_Error(interp);
2448 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002449 PyTuple_SET_ITEM(args, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002450 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002451
2452 res = PyObject_Call(data->func, args, NULL);
2453 Py_DECREF(args);
Guido van Rossum18468821994-06-20 07:49:28 +00002454
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002455 if (res == NULL)
2456 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002457
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002458 obj_res = AsObj(res);
2459 if (obj_res == NULL) {
2460 Py_DECREF(res);
2461 return PythonCmd_Error(interp);
2462 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002463 Tcl_SetObjResult(interp, obj_res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002464 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002465
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002466 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002467
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002468 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +00002469}
2470
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002471
Guido van Rossum18468821994-06-20 07:49:28 +00002472static void
Fred Drake509d79a2000-07-08 04:04:38 +00002473PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002474{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002475 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 ENTER_PYTHON
2478 Py_XDECREF(data->self);
2479 Py_XDECREF(data->func);
Victor Stinner00d7abd2020-12-01 09:56:42 +01002480 PyMem_Free(data);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002481 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002482}
2483
Barry Warsawfa701a81997-01-16 00:15:11 +00002484
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002485
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002486
2487TCL_DECLARE_MUTEX(command_mutex)
2488
2489typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002490 Tcl_Event ev;
2491 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002492 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002493 int create;
2494 int *status;
2495 ClientData *data;
2496 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002497} CommandEvent;
2498
2499static int
2500Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002501{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002502 if (ev->create)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002503 *ev->status = Tcl_CreateObjCommand(
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002504 ev->interp, ev->name, PythonCmd,
2505 ev->data, PythonCmdDelete) == NULL;
2506 else
2507 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2508 Tcl_MutexLock(&command_mutex);
2509 Tcl_ConditionNotify(ev->done);
2510 Tcl_MutexUnlock(&command_mutex);
2511 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002512}
2513
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002514/*[clinic input]
2515_tkinter.tkapp.createcommand
2516
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002517 name: str
2518 func: object
2519 /
2520
2521[clinic start generated code]*/
2522
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002523static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002524_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2525 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002526/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002527{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002528 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002529 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002530
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002531 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002532 if (!PyCallable_Check(func)) {
2533 PyErr_SetString(PyExc_TypeError, "command not callable");
2534 return NULL;
2535 }
Guido van Rossum18468821994-06-20 07:49:28 +00002536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002537 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2538 !WaitForMainloop(self))
2539 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002541 data = PyMem_NEW(PythonCmd_ClientData, 1);
2542 if (!data)
2543 return PyErr_NoMemory();
2544 Py_INCREF(self);
2545 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002546 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002547 data->func = func;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002548 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2549 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002550 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2551 if (ev == NULL) {
2552 PyErr_NoMemory();
Victor Stinner00d7abd2020-12-01 09:56:42 +01002553 PyMem_Free(data);
Serhiy Storchaka07940882014-09-11 10:38:54 +03002554 return NULL;
2555 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002556 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2557 ev->interp = self->interp;
2558 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002559 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560 ev->data = (ClientData)data;
2561 ev->status = &err;
2562 ev->done = &cond;
2563 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2564 Tcl_ConditionFinalize(&cond);
2565 }
2566 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002567 {
2568 ENTER_TCL
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002569 err = Tcl_CreateObjCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002570 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002571 (ClientData)data, PythonCmdDelete) == NULL;
2572 LEAVE_TCL
2573 }
2574 if (err) {
2575 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Victor Stinner00d7abd2020-12-01 09:56:42 +01002576 PyMem_Free(data);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002577 return NULL;
2578 }
Guido van Rossum18468821994-06-20 07:49:28 +00002579
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002580 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002581}
2582
Barry Warsawfa701a81997-01-16 00:15:11 +00002583
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002584
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002585/*[clinic input]
2586_tkinter.tkapp.deletecommand
2587
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002588 name: str
2589 /
2590
2591[clinic start generated code]*/
2592
Guido van Rossum18468821994-06-20 07:49:28 +00002593static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002594_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002595/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002596{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002597 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002598
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002599 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002601 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2602 Tcl_Condition cond = NULL;
2603 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002604 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2605 if (ev == NULL) {
2606 PyErr_NoMemory();
2607 return NULL;
2608 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002609 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2610 ev->interp = self->interp;
2611 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002612 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002613 ev->status = &err;
2614 ev->done = &cond;
2615 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2616 &command_mutex);
2617 Tcl_ConditionFinalize(&cond);
2618 }
2619 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002620 {
2621 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002622 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002623 LEAVE_TCL
2624 }
2625 if (err == -1) {
2626 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2627 return NULL;
2628 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002629 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002630}
2631
Barry Warsawfa701a81997-01-16 00:15:11 +00002632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002633
Guido van Rossum00d93061998-05-28 23:06:38 +00002634#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002635/** File Handler **/
2636
Guido van Rossum00d93061998-05-28 23:06:38 +00002637typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002638 PyObject *func;
2639 PyObject *file;
2640 int id;
2641 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002642} FileHandler_ClientData;
2643
2644static FileHandler_ClientData *HeadFHCD;
2645
2646static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002647NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002648{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002649 FileHandler_ClientData *p;
2650 p = PyMem_NEW(FileHandler_ClientData, 1);
2651 if (p != NULL) {
2652 Py_XINCREF(func);
2653 Py_XINCREF(file);
2654 p->func = func;
2655 p->file = file;
2656 p->id = id;
2657 p->next = HeadFHCD;
2658 HeadFHCD = p;
2659 }
2660 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002661}
2662
2663static void
Fred Drake509d79a2000-07-08 04:04:38 +00002664DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002665{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002666 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002668 pp = &HeadFHCD;
2669 while ((p = *pp) != NULL) {
2670 if (p->id == id) {
2671 *pp = p->next;
2672 Py_XDECREF(p->func);
2673 Py_XDECREF(p->file);
Victor Stinner00d7abd2020-12-01 09:56:42 +01002674 PyMem_Free(p);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002675 }
2676 else
2677 pp = &p->next;
2678 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002679}
2680
Guido van Rossuma597dde1995-01-10 20:56:29 +00002681static void
Fred Drake509d79a2000-07-08 04:04:38 +00002682FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002683{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002684 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
INADA Naoki72dccde2017-02-16 09:26:01 +09002685 PyObject *func, *file, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002686
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002687 ENTER_PYTHON
2688 func = data->func;
2689 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002690
INADA Naoki72dccde2017-02-16 09:26:01 +09002691 res = PyObject_CallFunction(func, "Oi", file, mask);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002692 if (res == NULL) {
2693 errorInCmd = 1;
2694 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2695 }
2696 Py_XDECREF(res);
2697 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002698}
2699
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002700/*[clinic input]
2701_tkinter.tkapp.createfilehandler
2702
2703 file: object
2704 mask: int
2705 func: object
2706 /
2707
2708[clinic start generated code]*/
2709
Guido van Rossum18468821994-06-20 07:49:28 +00002710static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002711_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2712 int mask, PyObject *func)
2713/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002714{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002715 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002716 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002718 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002719
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002720 tfile = PyObject_AsFileDescriptor(file);
2721 if (tfile < 0)
2722 return NULL;
2723 if (!PyCallable_Check(func)) {
2724 PyErr_SetString(PyExc_TypeError, "bad argument list");
2725 return NULL;
2726 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002727
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002728 data = NewFHCD(func, file, tfile);
2729 if (data == NULL)
2730 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002731
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002732 /* Ought to check for null Tcl_File object... */
2733 ENTER_TCL
2734 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2735 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002736 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002737}
2738
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002739/*[clinic input]
2740_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002741
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002742 file: object
2743 /
2744
2745[clinic start generated code]*/
2746
2747static PyObject *
2748_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2749/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2750{
2751 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002752
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002753 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002754
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002755 tfile = PyObject_AsFileDescriptor(file);
2756 if (tfile < 0)
2757 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002758
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002759 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002760
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002761 /* Ought to check for null Tcl_File object... */
2762 ENTER_TCL
2763 Tcl_DeleteFileHandler(tfile);
2764 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002765 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002766}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002767#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002769
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002770/**** Tktt Object (timer token) ****/
2771
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002772static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002773
Guido van Rossum00d93061998-05-28 23:06:38 +00002774typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002775 PyObject_HEAD
2776 Tcl_TimerToken token;
2777 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002778} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002779
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002780/*[clinic input]
2781_tkinter.tktimertoken.deletetimerhandler
2782
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002783[clinic start generated code]*/
2784
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002785static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002786_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002787/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002788{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002789 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002790 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002791
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002792 if (v->token != NULL) {
2793 Tcl_DeleteTimerHandler(v->token);
2794 v->token = NULL;
2795 }
2796 if (func != NULL) {
2797 v->func = NULL;
2798 Py_DECREF(func);
2799 Py_DECREF(v); /* See Tktt_New() */
2800 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002801 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002802}
2803
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002804static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002805Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002806{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002807 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002808
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002809 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002810 if (v == NULL)
2811 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002812
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002813 Py_INCREF(func);
2814 v->token = NULL;
2815 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002816
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002817 /* Extra reference, deleted when called or when handler is deleted */
2818 Py_INCREF(v);
2819 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002820}
2821
2822static void
Fred Drake509d79a2000-07-08 04:04:38 +00002823Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002824{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002825 TkttObject *v = (TkttObject *)self;
2826 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002827 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002828
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002829 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002830
Victor Stinner32bd68c2020-12-01 10:37:39 +01002831 PyObject_Free(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002832 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002833}
2834
Guido van Rossum597ac201998-05-12 14:36:19 +00002835static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002836Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002837{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002838 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002839 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2840 v,
2841 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002842}
2843
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002844/** Timer Handler **/
2845
2846static void
Fred Drake509d79a2000-07-08 04:04:38 +00002847TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002848{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002849 TkttObject *v = (TkttObject *)clientData;
2850 PyObject *func = v->func;
2851 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002852
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002853 if (func == NULL)
2854 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002855
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002856 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002857
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002858 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002859
Victor Stinner2ff58a22019-06-17 14:27:23 +02002860 res = PyObject_CallNoArgs(func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002861 Py_DECREF(func);
2862 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002863
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002864 if (res == NULL) {
2865 errorInCmd = 1;
2866 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2867 }
2868 else
2869 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002870
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002871 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002872}
2873
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002874/*[clinic input]
2875_tkinter.tkapp.createtimerhandler
2876
2877 milliseconds: int
2878 func: object
2879 /
2880
2881[clinic start generated code]*/
2882
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002883static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002884_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2885 PyObject *func)
2886/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002887{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002888 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002890 if (!PyCallable_Check(func)) {
2891 PyErr_SetString(PyExc_TypeError, "bad argument list");
2892 return NULL;
2893 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002894
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002895 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002896
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002897 v = Tktt_New(func);
2898 if (v) {
2899 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2900 (ClientData)v);
2901 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002902
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002903 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002904}
2905
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002906
Guido van Rossum18468821994-06-20 07:49:28 +00002907/** Event Loop **/
2908
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002909/*[clinic input]
2910_tkinter.tkapp.mainloop
2911
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002912 threshold: int = 0
2913 /
2914
2915[clinic start generated code]*/
2916
Guido van Rossum18468821994-06-20 07:49:28 +00002917static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002918_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002919/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002920{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002921 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002922
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002923 CHECK_TCL_APPARTMENT;
2924 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002925
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002926 quitMainLoop = 0;
2927 while (Tk_GetNumMainWindows() > threshold &&
2928 !quitMainLoop &&
2929 !errorInCmd)
2930 {
2931 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002932
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002933 if (self->threaded) {
2934 /* Allow other Python threads to run. */
2935 ENTER_TCL
2936 result = Tcl_DoOneEvent(0);
2937 LEAVE_TCL
2938 }
2939 else {
2940 Py_BEGIN_ALLOW_THREADS
2941 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2942 tcl_tstate = tstate;
2943 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2944 tcl_tstate = NULL;
2945 if(tcl_lock)PyThread_release_lock(tcl_lock);
2946 if (result == 0)
2947 Sleep(Tkinter_busywaitinterval);
2948 Py_END_ALLOW_THREADS
2949 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002950
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002951 if (PyErr_CheckSignals() != 0) {
2952 self->dispatching = 0;
2953 return NULL;
2954 }
2955 if (result < 0)
2956 break;
2957 }
2958 self->dispatching = 0;
2959 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002960
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002961 if (errorInCmd) {
2962 errorInCmd = 0;
2963 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2964 excInCmd = valInCmd = trbInCmd = NULL;
2965 return NULL;
2966 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002967 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002968}
2969
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002970/*[clinic input]
2971_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002972
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002973 flags: int = 0
2974 /
2975
2976[clinic start generated code]*/
2977
2978static PyObject *
2979_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2980/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2981{
2982 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002983
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002984 ENTER_TCL
2985 rv = Tcl_DoOneEvent(flags);
2986 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002987 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002988}
2989
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002990/*[clinic input]
2991_tkinter.tkapp.quit
2992[clinic start generated code]*/
2993
Guido van Rossum062cfb01995-01-10 17:42:51 +00002994static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002995_tkinter_tkapp_quit_impl(TkappObject *self)
2996/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002997{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002998 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002999 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00003000}
3001
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003002/*[clinic input]
3003_tkinter.tkapp.interpaddr
3004[clinic start generated code]*/
3005
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003006static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003007_tkinter_tkapp_interpaddr_impl(TkappObject *self)
3008/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003009{
Victor Stinnere1040e22013-09-05 00:22:24 +02003010 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003011}
3012
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003013/*[clinic input]
3014_tkinter.tkapp.loadtk
3015[clinic start generated code]*/
3016
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003017static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003018_tkinter_tkapp_loadtk_impl(TkappObject *self)
3019/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00003020{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003021 Tcl_Interp *interp = Tkapp_Interp(self);
3022 const char * _tk_exists = NULL;
3023 int err;
David Aschere2b4b322004-02-18 05:59:53 +00003024
Guilherme Polob681df42009-02-09 22:33:59 +00003025#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003026 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
3027 * first call failed.
3028 * To avoid the deadlock, we just refuse the second call through
3029 * a static variable.
3030 */
3031 if (tk_load_failed) {
3032 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
3033 return NULL;
3034 }
Guilherme Polob681df42009-02-09 22:33:59 +00003035#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003036
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003037 /* We want to guard against calling Tk_Init() multiple times */
3038 CHECK_TCL_APPARTMENT;
3039 ENTER_TCL
3040 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
3041 ENTER_OVERLAP
3042 if (err == TCL_ERROR) {
3043 /* This sets an exception, but we cannot return right
3044 away because we need to exit the overlap first. */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03003045 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003046 } else {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03003047 _tk_exists = Tcl_GetStringResult(Tkapp_Interp(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003048 }
3049 LEAVE_OVERLAP_TCL
3050 if (err == TCL_ERROR) {
3051 return NULL;
3052 }
3053 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
3054 if (Tk_Init(interp) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03003055 Tkinter_Error(self);
Guilherme Polob681df42009-02-09 22:33:59 +00003056#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003057 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00003058#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003059 return NULL;
3060 }
3061 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003062 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00003063}
Barry Warsawfa701a81997-01-16 00:15:11 +00003064
Martin v. Löwisffad6332002-11-26 09:28:05 +00003065static PyObject *
3066Tkapp_WantObjects(PyObject *self, PyObject *args)
3067{
3068
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003069 int wantobjects = -1;
3070 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3071 return NULL;
3072 if (wantobjects == -1)
3073 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3074 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003075
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003076 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003077}
3078
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003079/*[clinic input]
3080_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003081
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003082[clinic start generated code]*/
3083
3084static PyObject *
3085_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03003086/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003087{
3088 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003089
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003090 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003091}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003092
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003093
Guido van Rossum18468821994-06-20 07:49:28 +00003094/**** Tkapp Type Methods ****/
3095
3096static void
Fred Drake509d79a2000-07-08 04:04:38 +00003097Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003098{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003099 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003100 /*CHECK_TCL_APPARTMENT;*/
3101 ENTER_TCL
3102 Tcl_DeleteInterp(Tkapp_Interp(self));
3103 LEAVE_TCL
Victor Stinner32bd68c2020-12-01 10:37:39 +01003104 PyObject_Free(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003105 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003106 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003107}
3108
Barry Warsawfa701a81997-01-16 00:15:11 +00003109
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003110
Guido van Rossum18468821994-06-20 07:49:28 +00003111/**** Tkinter Module ****/
3112
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003113typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003114 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003115 Py_ssize_t size; /* current size */
3116 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003117} FlattenContext;
3118
3119static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003120_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003121{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003122 /* expand tuple to hold (at least) size new items.
3123 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003124
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003125 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003126
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003127 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003128 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003129
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003130 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003131
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003132 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003133}
3134
3135static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003136_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003137{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003138 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003139
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003140 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003141
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003142 if (depth > 1000) {
3143 PyErr_SetString(PyExc_ValueError,
3144 "nesting too deep in _flatten");
3145 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003146 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3147 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003148 /* preallocate (assume no nesting) */
3149 if (context->size + size > context->maxsize &&
3150 !_bump(context, size))
3151 return 0;
3152 /* copy items to output tuple */
3153 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003154 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003155 if (PyList_Check(o) || PyTuple_Check(o)) {
3156 if (!_flatten1(context, o, depth + 1))
3157 return 0;
3158 } else if (o != Py_None) {
3159 if (context->size + 1 > context->maxsize &&
3160 !_bump(context, 1))
3161 return 0;
3162 Py_INCREF(o);
3163 PyTuple_SET_ITEM(context->tuple,
3164 context->size++, o);
3165 }
3166 }
3167 } else {
3168 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3169 return 0;
3170 }
3171 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003172}
3173
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003174/*[clinic input]
3175_tkinter._flatten
3176
3177 item: object
3178 /
3179
3180[clinic start generated code]*/
3181
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003182static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003183_tkinter__flatten(PyObject *module, PyObject *item)
3184/*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003185{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003186 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003187
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003188 context.maxsize = PySequence_Size(item);
3189 if (context.maxsize < 0)
3190 return NULL;
3191 if (context.maxsize == 0)
3192 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003193
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003194 context.tuple = PyTuple_New(context.maxsize);
3195 if (!context.tuple)
3196 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003198 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003199
Miss Islington (bot)7e1d6302021-07-13 22:40:10 -07003200 if (!_flatten1(&context, item, 0)) {
3201 Py_XDECREF(context.tuple);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003202 return NULL;
Miss Islington (bot)7e1d6302021-07-13 22:40:10 -07003203 }
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003204
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003205 if (_PyTuple_Resize(&context.tuple, context.size))
3206 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003207
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003208 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003209}
3210
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003211/*[clinic input]
3212_tkinter.create
3213
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003214 screenName: str(accept={str, NoneType}) = None
3215 baseName: str = ""
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003216 className: str = "Tk"
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003217 interactive: bool(accept={int}) = False
3218 wantobjects: bool(accept={int}) = False
3219 wantTk: bool(accept={int}) = True
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003220 if false, then Tk_Init() doesn't get called
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003221 sync: bool(accept={int}) = False
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003222 if true, then pass -sync to wish
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003223 use: str(accept={str, NoneType}) = None
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003224 if not None, then pass -use to wish
3225 /
3226
3227[clinic start generated code]*/
3228
Guido van Rossum18468821994-06-20 07:49:28 +00003229static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003230_tkinter_create_impl(PyObject *module, const char *screenName,
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003231 const char *baseName, const char *className,
3232 int interactive, int wantobjects, int wantTk, int sync,
3233 const char *use)
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003234/*[clinic end generated code: output=e3315607648e6bb4 input=da9b17ee7358d862]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003235{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003236 /* XXX baseName is not used anymore;
3237 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003238 CHECK_STRING_LENGTH(screenName);
3239 CHECK_STRING_LENGTH(baseName);
3240 CHECK_STRING_LENGTH(className);
3241 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003242
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003243 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003244 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003245 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003246}
3247
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003248/*[clinic input]
3249_tkinter.setbusywaitinterval
3250
3251 new_val: int
3252 /
3253
3254Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3255
3256It should be set to a divisor of the maximum time between frames in an animation.
3257[clinic start generated code]*/
3258
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003259static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003260_tkinter_setbusywaitinterval_impl(PyObject *module, int new_val)
3261/*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003262{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003263 if (new_val < 0) {
3264 PyErr_SetString(PyExc_ValueError,
3265 "busywaitinterval must be >= 0");
3266 return NULL;
3267 }
3268 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003269 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003270}
3271
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003272/*[clinic input]
3273_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003274
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003275Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3276[clinic start generated code]*/
3277
3278static int
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003279_tkinter_getbusywaitinterval_impl(PyObject *module)
3280/*[clinic end generated code: output=23b72d552001f5c7 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003281{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003282 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003283}
3284
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003285#include "clinic/_tkinter.c.h"
3286
3287static PyMethodDef Tktt_methods[] =
3288{
3289 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3290 {NULL, NULL}
3291};
3292
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003293static PyType_Slot Tktt_Type_slots[] = {
3294 {Py_tp_dealloc, Tktt_Dealloc},
3295 {Py_tp_repr, Tktt_Repr},
3296 {Py_tp_methods, Tktt_methods},
3297 {0, 0}
3298};
3299
3300static PyType_Spec Tktt_Type_spec = {
3301 "_tkinter.tktimertoken",
3302 sizeof(TkttObject),
3303 0,
Victor Stinner3bb09942021-04-30 12:46:15 +02003304 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003305 Tktt_Type_slots,
3306};
3307
3308
3309/**** Tkapp Method List ****/
3310
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003311static PyMethodDef Tkapp_methods[] =
3312{
3313 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3314 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3315 {"call", Tkapp_Call, METH_VARARGS},
3316 _TKINTER_TKAPP_EVAL_METHODDEF
3317 _TKINTER_TKAPP_EVALFILE_METHODDEF
3318 _TKINTER_TKAPP_RECORD_METHODDEF
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03003319 _TKINTER_TKAPP_ADDERRORINFO_METHODDEF
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003320 {"setvar", Tkapp_SetVar, METH_VARARGS},
3321 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3322 {"getvar", Tkapp_GetVar, METH_VARARGS},
3323 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3324 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3325 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3326 _TKINTER_TKAPP_GETINT_METHODDEF
3327 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3328 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3329 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3330 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3331 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3332 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3333 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3334 _TKINTER_TKAPP_SPLIT_METHODDEF
3335 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3336 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3337 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3338 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3339 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3340 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3341 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3342 _TKINTER_TKAPP_QUIT_METHODDEF
3343 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3344 _TKINTER_TKAPP_LOADTK_METHODDEF
3345 {NULL, NULL}
3346};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003347
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003348static PyType_Slot Tkapp_Type_slots[] = {
3349 {Py_tp_dealloc, Tkapp_Dealloc},
3350 {Py_tp_methods, Tkapp_methods},
3351 {0, 0}
3352};
3353
3354
3355static PyType_Spec Tkapp_Type_spec = {
3356 "_tkinter.tkapp",
3357 sizeof(TkappObject),
3358 0,
Victor Stinner3bb09942021-04-30 12:46:15 +02003359 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003360 Tkapp_Type_slots,
3361};
3362
Guido van Rossum18468821994-06-20 07:49:28 +00003363static PyMethodDef moduleMethods[] =
3364{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003365 _TKINTER__FLATTEN_METHODDEF
3366 _TKINTER_CREATE_METHODDEF
3367 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3368 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003369 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003370};
3371
Guido van Rossum7bf15641998-05-22 18:28:17 +00003372#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003373
3374static int stdin_ready = 0;
3375
Guido van Rossumad4db171998-06-13 13:56:28 +00003376#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003377static void
Fred Drake509d79a2000-07-08 04:04:38 +00003378MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003379{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003380 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003381}
Guido van Rossumad4db171998-06-13 13:56:28 +00003382#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003383
Guido van Rossum00d93061998-05-28 23:06:38 +00003384static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003385
Guido van Rossum18468821994-06-20 07:49:28 +00003386static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003387EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003388{
Guido van Rossumad4db171998-06-13 13:56:28 +00003389#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003390 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003391#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003392 PyEval_RestoreThread(event_tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003393 stdin_ready = 0;
3394 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003395#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003396 tfile = fileno(stdin);
3397 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003398#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003399 while (!errorInCmd && !stdin_ready) {
3400 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003401#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003402 if (_kbhit()) {
3403 stdin_ready = 1;
3404 break;
3405 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003406#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003407 Py_BEGIN_ALLOW_THREADS
3408 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3409 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003411 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003413 tcl_tstate = NULL;
3414 if(tcl_lock)PyThread_release_lock(tcl_lock);
3415 if (result == 0)
3416 Sleep(Tkinter_busywaitinterval);
3417 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003418
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003419 if (result < 0)
3420 break;
3421 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003422#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003423 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003424#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003425 if (errorInCmd) {
3426 errorInCmd = 0;
3427 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3428 excInCmd = valInCmd = trbInCmd = NULL;
3429 PyErr_Print();
3430 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003431 PyEval_SaveThread();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003432 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003433}
Guido van Rossum18468821994-06-20 07:49:28 +00003434
Guido van Rossum00d93061998-05-28 23:06:38 +00003435#endif
3436
Guido van Rossum7bf15641998-05-22 18:28:17 +00003437static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003438EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003439{
Guido van Rossum00d93061998-05-28 23:06:38 +00003440#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003441 if (PyOS_InputHook == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003442 event_tstate = PyThreadState_Get();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003443 PyOS_InputHook = EventHook;
3444 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003445#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003446}
3447
3448static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003449DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003450{
Guido van Rossum00d93061998-05-28 23:06:38 +00003451#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003452 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3453 PyOS_InputHook = NULL;
3454 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003455#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003456}
3457
Barry Warsawfa701a81997-01-16 00:15:11 +00003458
Martin v. Löwis1a214512008-06-11 05:26:20 +00003459static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003460 PyModuleDef_HEAD_INIT,
3461 "_tkinter",
3462 NULL,
3463 -1,
3464 moduleMethods,
3465 NULL,
3466 NULL,
3467 NULL,
3468 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003469};
3470
Mark Hammond62b1ab12002-07-23 06:31:15 +00003471PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003472PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003473{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003474 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003475
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003476 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003477 if (tcl_lock == NULL)
3478 return NULL;
Guido van Rossumae92f011996-08-21 19:03:36 +00003479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003480 m = PyModule_Create(&_tkintermodule);
3481 if (m == NULL)
3482 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003483
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003484 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3485 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003486 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003487 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003488 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003489 Py_INCREF(o);
3490 if (PyModule_AddObject(m, "TclError", o)) {
3491 Py_DECREF(o);
3492 Py_DECREF(m);
3493 return NULL;
3494 }
3495 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003496
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003497 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3498 Py_DECREF(m);
3499 return NULL;
3500 }
3501 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3502 Py_DECREF(m);
3503 return NULL;
3504 }
3505 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3506 Py_DECREF(m);
3507 return NULL;
3508 }
3509 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3510 Py_DECREF(m);
3511 return NULL;
3512 }
3513 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3514 Py_DECREF(m);
3515 return NULL;
3516 }
3517 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3518 Py_DECREF(m);
3519 return NULL;
3520 }
3521 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3522 Py_DECREF(m);
3523 return NULL;
3524 }
3525 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3526 Py_DECREF(m);
3527 return NULL;
3528 }
3529 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3530 Py_DECREF(m);
3531 return NULL;
3532 }
3533 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3534 Py_DECREF(m);
3535 return NULL;
3536 }
3537 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3538 Py_DECREF(m);
3539 return NULL;
3540 }
3541
3542 o = PyType_FromSpec(&Tkapp_Type_spec);
3543 if (o == NULL) {
3544 Py_DECREF(m);
3545 return NULL;
3546 }
3547 if (PyModule_AddObject(m, "TkappType", o)) {
3548 Py_DECREF(o);
3549 Py_DECREF(m);
3550 return NULL;
3551 }
3552 Tkapp_Type = o;
3553
3554 o = PyType_FromSpec(&Tktt_Type_spec);
3555 if (o == NULL) {
3556 Py_DECREF(m);
3557 return NULL;
3558 }
3559 if (PyModule_AddObject(m, "TkttType", o)) {
3560 Py_DECREF(o);
3561 Py_DECREF(m);
3562 return NULL;
3563 }
3564 Tktt_Type = o;
3565
3566 o = PyType_FromSpec(&PyTclObject_Type_spec);
3567 if (o == NULL) {
3568 Py_DECREF(m);
3569 return NULL;
3570 }
3571 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3572 Py_DECREF(o);
3573 Py_DECREF(m);
3574 return NULL;
3575 }
3576 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003577
3578#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003579 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3580 * start waking up. Note that Tcl_FindExecutable will do this, this
3581 * code must be above it! The original warning from
3582 * tkMacOSXAppInit.c is copied below.
3583 *
3584 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3585 * Tcl interpreter for now. It probably should work to do this
3586 * in the other order, but for now it doesn't seem to.
3587 *
3588 */
3589 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003590#endif
3591
3592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003593 /* This helps the dynamic loader; in Unicode aware Tcl versions
3594 it also helps Tcl find its encodings. */
3595 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3596 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003597 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003598 if (cexe) {
3599#ifdef MS_WINDOWS
3600 int set_var = 0;
3601 PyObject *str_path;
3602 wchar_t *wcs_path;
3603 DWORD ret;
3604
3605 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3606
3607 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3608 str_path = _get_tcl_lib_path();
3609 if (str_path == NULL && PyErr_Occurred()) {
Brandt Bucher289cf0f2019-11-18 06:52:36 -08003610 Py_DECREF(m);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003611 return NULL;
3612 }
3613 if (str_path != NULL) {
3614 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3615 if (wcs_path == NULL) {
Brandt Bucher289cf0f2019-11-18 06:52:36 -08003616 Py_DECREF(m);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003617 return NULL;
3618 }
3619 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3620 set_var = 1;
3621 }
3622 }
3623
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003624 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003625
3626 if (set_var) {
3627 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3628 PyMem_Free(wcs_path);
3629 }
3630#else
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003631 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003632#endif /* MS_WINDOWS */
3633 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003634 Py_XDECREF(cexe);
3635 Py_DECREF(uexe);
3636 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003637
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003638 if (PyErr_Occurred()) {
3639 Py_DECREF(m);
3640 return NULL;
3641 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003642
Guido van Rossum43ff8681998-07-14 18:02:13 +00003643#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003644 /* This was not a good idea; through <Destroy> bindings,
3645 Tcl_Finalize() may invoke Python code but at that point the
3646 interpreter and thread state have already been destroyed! */
3647 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003648#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003649 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003650}