blob: 793c5e71548846345c937e6728f11bef6272e1b9 [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 \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000249 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
250 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000251
252#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300253 tcl_tstate = NULL; \
254 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000255
Guido van Rossum62320c91998-06-15 04:36:09 +0000256#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000257 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000258
259#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000261
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000262#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000263 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300264 if(tcl_lock) \
265 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000266
267#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000268 { PyThreadState *tstate = PyEval_SaveThread(); \
269 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000270
271#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000272 if (((TkappObject *)self)->threaded && \
273 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300274 PyErr_SetString(PyExc_RuntimeError, \
luzpaza5293b42017-11-05 07:37:50 -0600275 "Calling Tcl from different apartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000276 return 0; \
277 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000278
Guido van Rossum97867b21996-08-08 19:09:53 +0000279#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000280#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000281#endif
282
Guido van Rossum18468821994-06-20 07:49:28 +0000283/**** Tkapp Object Declaration ****/
284
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300285static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000286
Guido van Rossum00d93061998-05-28 23:06:38 +0000287typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000288 PyObject_HEAD
289 Tcl_Interp *interp;
290 int wantobjects;
291 int threaded; /* True if tcl_platform[threaded] */
292 Tcl_ThreadId thread_id;
293 int dispatching;
294 /* We cannot include tclInt.h, as this is internal.
295 So we cache interesting types here. */
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200296 const Tcl_ObjType *OldBooleanType;
Zachary Ware037605b2014-08-05 11:54:34 -0500297 const Tcl_ObjType *BooleanType;
298 const Tcl_ObjType *ByteArrayType;
299 const Tcl_ObjType *DoubleType;
300 const Tcl_ObjType *IntType;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300301 const Tcl_ObjType *WideIntType;
302 const Tcl_ObjType *BignumType;
Zachary Ware037605b2014-08-05 11:54:34 -0500303 const Tcl_ObjType *ListType;
304 const Tcl_ObjType *ProcBodyType;
305 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000306} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000307
Guido van Rossum18468821994-06-20 07:49:28 +0000308#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000309
Guido van Rossum35d43371997-08-02 00:09:09 +0000310#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000311(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000312
Barry Warsawfa701a81997-01-16 00:15:11 +0000313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000314
Guido van Rossum18468821994-06-20 07:49:28 +0000315/**** Error Handling ****/
316
317static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000318static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000319static int errorInCmd = 0;
320static PyObject *excInCmd;
321static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000322static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000323
Guilherme Polob681df42009-02-09 22:33:59 +0000324#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000325static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000326#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000327
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000328
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300329static PyObject *Tkapp_UnicodeResult(TkappObject *);
330
Guido van Rossum18468821994-06-20 07:49:28 +0000331static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300332Tkinter_Error(TkappObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +0000333{
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300334 PyObject *res = Tkapp_UnicodeResult(self);
335 if (res != NULL) {
336 PyErr_SetObject(Tkinter_TclError, res);
337 Py_DECREF(res);
338 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000339 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000340}
341
Barry Warsawfa701a81997-01-16 00:15:11 +0000342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000343
Guido van Rossum18468821994-06-20 07:49:28 +0000344/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000345
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000346static int Tkinter_busywaitinterval = 20;
347
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000348#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000349
Guido van Rossum00d93061998-05-28 23:06:38 +0000350/* Millisecond sleep() for Unix platforms. */
351
352static void
Fred Drake509d79a2000-07-08 04:04:38 +0000353Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000354{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000355 /* XXX Too bad if you don't have select(). */
356 struct timeval t;
357 t.tv_sec = milli/1000;
358 t.tv_usec = (milli%1000) * 1000;
359 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000360}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000361#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000362
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000363/* Wait up to 1s for the mainloop to come up. */
364
365static int
366WaitForMainloop(TkappObject* self)
367{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000368 int i;
369 for (i = 0; i < 10; i++) {
370 if (self->dispatching)
371 return 1;
372 Py_BEGIN_ALLOW_THREADS
373 Sleep(100);
374 Py_END_ALLOW_THREADS
375 }
376 if (self->dispatching)
377 return 1;
378 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
379 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000380}
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000382
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000383
Guido van Rossum18468821994-06-20 07:49:28 +0000384#define ARGSZ 64
385
Barry Warsawfa701a81997-01-16 00:15:11 +0000386
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387
Guido van Rossum18468821994-06-20 07:49:28 +0000388static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200389unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
390{
391 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300392 if (r != NULL || !PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
393 return r;
394 }
395
396 char *buf = NULL;
397 PyErr_Clear();
398 /* Tcl encodes null character as \xc0\x80 */
399 if (memchr(s, '\xc0', size)) {
400 char *q;
401 const char *e = s + size;
402 q = buf = (char *)PyMem_Malloc(size);
403 if (buf == NULL) {
404 PyErr_NoMemory();
405 return NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200406 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300407 while (s != e) {
408 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
409 *q++ = '\0';
410 s += 2;
411 }
412 else
413 *q++ = *s++;
414 }
415 s = buf;
416 size = q - s;
417 }
418 r = PyUnicode_DecodeUTF8(s, size, "surrogateescape");
419 if (buf != NULL) {
420 PyMem_Free(buf);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200421 }
422 return r;
423}
424
425static PyObject *
426unicodeFromTclString(const char *s)
427{
428 return unicodeFromTclStringAndSize(s, strlen(s));
429}
430
431static PyObject *
432unicodeFromTclObj(Tcl_Obj *value)
433{
434 int len;
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300435#if USE_TCL_UNICODE
436 int byteorder = NATIVE_BYTEORDER;
437 const Tcl_UniChar *u = Tcl_GetUnicodeFromObj(value, &len);
438 if (sizeof(Tcl_UniChar) == 2)
439 return PyUnicode_DecodeUTF16((const char *)u, len * 2,
440 "surrogatepass", &byteorder);
441 else if (sizeof(Tcl_UniChar) == 4)
442 return PyUnicode_DecodeUTF32((const char *)u, len * 4,
443 "surrogatepass", &byteorder);
444 else
445 Py_UNREACHABLE();
446#else
447 const char *s = Tcl_GetStringFromObj(value, &len);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200448 return unicodeFromTclStringAndSize(s, len);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300449#endif
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200450}
451
452
453static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300454Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000455{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000456 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300457 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000458 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000459
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000460 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300461 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000462 }
Guido van Rossum18468821994-06-20 07:49:28 +0000463
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000464 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
465 /* Not a list.
466 * Could be a quoted string containing funnies, e.g. {"}.
467 * Return the string itself.
468 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200469 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000470 }
Guido van Rossum18468821994-06-20 07:49:28 +0000471
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000472 if (argc == 0)
473 v = PyUnicode_FromString("");
474 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200475 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000476 else if ((v = PyTuple_New(argc)) != NULL) {
477 int i;
478 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000480 for (i = 0; i < argc; i++) {
481 if ((w = Split(argv[i])) == NULL) {
482 Py_DECREF(v);
483 v = NULL;
484 break;
485 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300486 PyTuple_SET_ITEM(v, i, w);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000487 }
488 }
489 Tcl_Free(FREECAST argv);
490 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000491}
492
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300493/* In some cases, Tcl will still return strings that are supposed to
494 be lists. SplitObj walks through a nested tuple, finding string
495 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000496
Martin v. Löwis59683e82008-06-13 07:50:45 +0000497static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000498SplitObj(PyObject *arg)
499{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000500 if (PyTuple_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200501 Py_ssize_t i, size;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000502 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000503
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300504 size = PyTuple_GET_SIZE(arg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000505 result = NULL;
506 /* Recursively invoke SplitObj for all tuple items.
507 If this does not return a new object, no action is
508 needed. */
509 for(i = 0; i < size; i++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300510 elem = PyTuple_GET_ITEM(arg, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000511 newelem = SplitObj(elem);
512 if (!newelem) {
513 Py_XDECREF(result);
514 return NULL;
515 }
516 if (!result) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200517 Py_ssize_t k;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000518 if (newelem == elem) {
519 Py_DECREF(newelem);
520 continue;
521 }
522 result = PyTuple_New(size);
523 if (!result)
524 return NULL;
525 for(k = 0; k < i; k++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300526 elem = PyTuple_GET_ITEM(arg, k);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000527 Py_INCREF(elem);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300528 PyTuple_SET_ITEM(result, k, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000529 }
530 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300531 PyTuple_SET_ITEM(result, i, newelem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000532 }
533 if (result)
534 return result;
535 /* Fall through, returning arg. */
536 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300537 else if (PyList_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200538 Py_ssize_t i, size;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300539 PyObject *elem, *newelem, *result;
540
541 size = PyList_GET_SIZE(arg);
542 result = PyTuple_New(size);
543 if (!result)
544 return NULL;
545 /* Recursively invoke SplitObj for all list items. */
546 for(i = 0; i < size; i++) {
547 elem = PyList_GET_ITEM(arg, i);
548 newelem = SplitObj(elem);
549 if (!newelem) {
550 Py_XDECREF(result);
551 return NULL;
552 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300553 PyTuple_SET_ITEM(result, i, newelem);
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300554 }
555 return result;
556 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300557 else if (PyUnicode_Check(arg)) {
558 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300559 const char **argv;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200560 const char *list = PyUnicode_AsUTF8(arg);
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300561
562 if (list == NULL ||
563 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
564 Py_INCREF(arg);
565 return arg;
566 }
567 Tcl_Free(FREECAST argv);
568 if (argc > 1)
569 return Split(list);
570 /* Fall through, returning arg. */
571 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000572 else if (PyBytes_Check(arg)) {
573 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300574 const char **argv;
Serhiy Storchaka8f87eef2020-04-12 14:58:27 +0300575 const char *list = PyBytes_AS_STRING(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000576
Serhiy Storchaka8f87eef2020-04-12 14:58:27 +0300577 if (Tcl_SplitList((Tcl_Interp *)NULL, (char *)list, &argc, &argv) != TCL_OK) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000578 Py_INCREF(arg);
579 return arg;
580 }
581 Tcl_Free(FREECAST argv);
582 if (argc > 1)
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300583 return Split(PyBytes_AS_STRING(arg));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000584 /* Fall through, returning arg. */
585 }
586 Py_INCREF(arg);
587 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000588}
Barry Warsawfa701a81997-01-16 00:15:11 +0000589
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000590
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +0300591/*[clinic input]
592module _tkinter
593class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec"
594class _tkinter.Tcl_Obj "PyTclObject *" "&PyTclObject_Type_spec"
595class _tkinter.tktimertoken "TkttObject *" "&Tktt_Type_spec"
596[clinic start generated code]*/
597/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b1ebf15c162ee229]*/
598
Guido van Rossum18468821994-06-20 07:49:28 +0000599/**** Tkapp Object ****/
600
601#ifndef WITH_APPINIT
602int
Fred Drake509d79a2000-07-08 04:04:38 +0000603Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000604{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000605 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 if (Tcl_Init(interp) == TCL_ERROR) {
608 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
609 return TCL_ERROR;
610 }
Guilherme Polob681df42009-02-09 22:33:59 +0000611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 _tkinter_skip_tk_init = Tcl_GetVar(interp,
613 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
614 if (_tkinter_skip_tk_init != NULL &&
615 strcmp(_tkinter_skip_tk_init, "1") == 0) {
616 return TCL_OK;
617 }
Guilherme Polob681df42009-02-09 22:33:59 +0000618
619#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000620 if (tk_load_failed) {
621 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
622 return TCL_ERROR;
623 }
Guilherme Polob681df42009-02-09 22:33:59 +0000624#endif
625
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000626 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000627#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000628 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000629#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
631 return TCL_ERROR;
632 }
Guilherme Polob681df42009-02-09 22:33:59 +0000633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000634 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000635}
636#endif /* !WITH_APPINIT */
637
Guido van Rossum18468821994-06-20 07:49:28 +0000638
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639
Barry Warsawfa701a81997-01-16 00:15:11 +0000640
641/* Initialize the Tk application; see the `main' function in
642 * `tkMain.c'.
643 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000644
Thomas Wouters58d05102000-07-24 14:43:35 +0000645static void EnableEventHook(void); /* Forward */
646static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000647
Barry Warsawfa701a81997-01-16 00:15:11 +0000648static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300649Tkapp_New(const char *screenName, const char *className,
650 int interactive, int wantobjects, int wantTk, int sync,
651 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000652{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 TkappObject *v;
654 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000655
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300656 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000657 if (v == NULL)
658 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000659
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 v->interp = Tcl_CreateInterp();
661 v->wantobjects = wantobjects;
662 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
663 TCL_GLOBAL_ONLY) != NULL;
664 v->thread_id = Tcl_GetCurrentThread();
665 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000666
667#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300669 PyErr_SetString(PyExc_RuntimeError,
670 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000671 Py_DECREF(v);
672 return 0;
673 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000674#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000675 if (v->threaded && tcl_lock) {
676 /* If Tcl is threaded, we don't need the lock. */
677 PyThread_free_lock(tcl_lock);
678 tcl_lock = NULL;
679 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000680
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200681 v->OldBooleanType = Tcl_GetObjType("boolean");
682 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000683 v->ByteArrayType = Tcl_GetObjType("bytearray");
684 v->DoubleType = Tcl_GetObjType("double");
685 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300686 v->WideIntType = Tcl_GetObjType("wideInt");
687 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000688 v->ListType = Tcl_GetObjType("list");
689 v->ProcBodyType = Tcl_GetObjType("procbody");
690 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000691
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000692 /* Delete the 'exit' command, which can screw things up */
693 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000695 if (screenName != NULL)
696 Tcl_SetVar2(v->interp, "env", "DISPLAY",
697 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000698
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000699 if (interactive)
700 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
701 else
702 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000703
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000704 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200705 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 if (!argv0) {
707 PyErr_NoMemory();
708 Py_DECREF(v);
709 return NULL;
710 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000711
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000712 strcpy(argv0, className);
Jordon Xu2ec70102019-09-11 00:04:08 +0800713 if (Py_ISUPPER(argv0[0]))
714 argv0[0] = Py_TOLOWER(argv0[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000715 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200716 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 if (! wantTk) {
719 Tcl_SetVar(v->interp,
720 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
721 }
Guilherme Polob681df42009-02-09 22:33:59 +0000722#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000723 else if (tk_load_failed) {
724 Tcl_SetVar(v->interp,
725 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
726 }
Guilherme Polob681df42009-02-09 22:33:59 +0000727#endif
David Aschere2b4b322004-02-18 05:59:53 +0000728
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000729 /* some initial arguments need to be in argv */
730 if (sync || use) {
731 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200732 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000733
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000734 if (sync)
735 len += sizeof "-sync";
736 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200737 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000738
Victor Stinneree6c3c72014-09-11 17:50:21 +0200739 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000740 if (!args) {
741 PyErr_NoMemory();
742 Py_DECREF(v);
743 return NULL;
744 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000745
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000746 args[0] = '\0';
747 if (sync)
748 strcat(args, "-sync");
749 if (use) {
750 if (sync)
751 strcat(args, " ");
752 strcat(args, "-use ");
753 strcat(args, use);
754 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000755
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000756 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200757 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000758 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000759
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500760#ifdef MS_WINDOWS
761 {
762 PyObject *str_path;
763 PyObject *utf8_path;
764 DWORD ret;
765
766 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
767 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
768 str_path = _get_tcl_lib_path();
769 if (str_path == NULL && PyErr_Occurred()) {
770 return NULL;
771 }
772 if (str_path != NULL) {
773 utf8_path = PyUnicode_AsUTF8String(str_path);
774 if (utf8_path == NULL) {
775 return NULL;
776 }
777 Tcl_SetVar(v->interp,
778 "tcl_library",
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300779 PyBytes_AS_STRING(utf8_path),
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500780 TCL_GLOBAL_ONLY);
781 Py_DECREF(utf8_path);
782 }
783 }
784 }
785#endif
786
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000787 if (Tcl_AppInit(v->interp) != TCL_OK) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300788 PyObject *result = Tkinter_Error(v);
Guilherme Polob681df42009-02-09 22:33:59 +0000789#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000790 if (wantTk) {
791 const char *_tkinter_tk_failed;
792 _tkinter_tk_failed = Tcl_GetVar(v->interp,
793 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000794
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000795 if ( _tkinter_tk_failed != NULL &&
796 strcmp(_tkinter_tk_failed, "1") == 0) {
797 tk_load_failed = 1;
798 }
799 }
Guilherme Polob681df42009-02-09 22:33:59 +0000800#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000801 Py_DECREF((PyObject *)v);
802 return (TkappObject *)result;
803 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000804
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000805 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000806
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000807 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000808}
809
Barry Warsawfa701a81997-01-16 00:15:11 +0000810
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000811static void
812Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000813 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000814{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000815 Py_BEGIN_ALLOW_THREADS;
816 Tcl_MutexLock(mutex);
817 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
818 Tcl_ThreadAlert(self->thread_id);
819 Tcl_ConditionWait(cond, mutex, NULL);
820 Tcl_MutexUnlock(mutex);
821 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000822}
823
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000824
Guido van Rossum18468821994-06-20 07:49:28 +0000825/** Tcl Eval **/
826
Martin v. Löwisffad6332002-11-26 09:28:05 +0000827typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000828 PyObject_HEAD
829 Tcl_Obj *value;
830 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000831} PyTclObject;
832
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300833static PyObject *PyTclObject_Type;
Dong-hee Na1b55b652020-02-17 19:09:15 +0900834#define PyTclObject_Check(v) Py_IS_TYPE(v, (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000835
836static PyObject *
837newPyTclObject(Tcl_Obj *arg)
838{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000839 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300840 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000841 if (self == NULL)
842 return NULL;
843 Tcl_IncrRefCount(arg);
844 self->value = arg;
845 self->string = NULL;
846 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000847}
848
849static void
850PyTclObject_dealloc(PyTclObject *self)
851{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200852 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000853 Tcl_DecrRefCount(self->value);
854 Py_XDECREF(self->string);
855 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200856 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000857}
858
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000859/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000860PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000861"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000862
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000863static PyObject *
864PyTclObject_string(PyTclObject *self, void *ignored)
865{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000866 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200867 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000868 if (!self->string)
869 return NULL;
870 }
871 Py_INCREF(self->string);
872 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000873}
874
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000875static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200876PyTclObject_str(PyTclObject *self)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000877{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200878 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000879 Py_INCREF(self->string);
880 return self->string;
881 }
882 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200883 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000884}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000885
Martin v. Löwisffad6332002-11-26 09:28:05 +0000886static PyObject *
887PyTclObject_repr(PyTclObject *self)
888{
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200889 PyObject *repr, *str = PyTclObject_str(self);
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300890 if (str == NULL)
891 return NULL;
892 repr = PyUnicode_FromFormat("<%s object: %R>",
893 self->value->typePtr->name, str);
894 Py_DECREF(str);
895 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000896}
897
Mark Dickinson211c6252009-02-01 10:28:51 +0000898static PyObject *
899PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000900{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000901 int result;
Mark Dickinson211c6252009-02-01 10:28:51 +0000902
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000903 /* neither argument should be NULL, unless something's gone wrong */
904 if (self == NULL || other == NULL) {
905 PyErr_BadInternalCall();
906 return NULL;
907 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000908
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000909 /* both arguments should be instances of PyTclObject */
910 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
stratakise8b19652017-11-02 11:32:54 +0100911 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000912 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000913
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000914 if (self == other)
915 /* fast path when self and other are identical */
916 result = 0;
917 else
918 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
919 Tcl_GetString(((PyTclObject *)other)->value));
stratakise8b19652017-11-02 11:32:54 +0100920 Py_RETURN_RICHCOMPARE(result, 0, op);
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000921}
922
Martin v. Löwis39195712003-01-04 00:33:13 +0000923PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
924
Martin v. Löwisffad6332002-11-26 09:28:05 +0000925static PyObject*
926get_typename(PyTclObject* obj, void* ignored)
927{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200928 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000929}
930
Martin v. Löwis39195712003-01-04 00:33:13 +0000931
Martin v. Löwisffad6332002-11-26 09:28:05 +0000932static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000933 {"typename", (getter)get_typename, NULL, get_typename__doc__},
934 {"string", (getter)PyTclObject_string, NULL,
935 PyTclObject_string__doc__},
936 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000937};
938
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300939static PyType_Slot PyTclObject_Type_slots[] = {
940 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
941 {Py_tp_repr, (reprfunc)PyTclObject_repr},
942 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200943 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300944 {Py_tp_richcompare, PyTclObject_richcompare},
945 {Py_tp_getset, PyTclObject_getsetlist},
946 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000947};
948
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300949static PyType_Spec PyTclObject_Type_spec = {
950 "_tkinter.Tcl_Obj",
951 sizeof(PyTclObject),
952 0,
953 Py_TPFLAGS_DEFAULT,
954 PyTclObject_Type_slots,
955};
956
957
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700958#if SIZE_MAX > INT_MAX
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300959#define CHECK_STRING_LENGTH(s) do { \
960 if (s != NULL && strlen(s) >= INT_MAX) { \
961 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
962 return NULL; \
963 } } while(0)
964#else
965#define CHECK_STRING_LENGTH(s)
966#endif
967
Andrew York003708b2020-05-15 03:43:58 -0700968#ifdef HAVE_LIBTOMMATH
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300969static Tcl_Obj*
970asBignumObj(PyObject *value)
971{
972 Tcl_Obj *result;
973 int neg;
974 PyObject *hexstr;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200975 const char *hexchars;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300976 mp_int bigValue;
977
978 neg = Py_SIZE(value) < 0;
979 hexstr = _PyLong_Format(value, 16);
980 if (hexstr == NULL)
981 return NULL;
982 hexchars = PyUnicode_AsUTF8(hexstr);
983 if (hexchars == NULL) {
984 Py_DECREF(hexstr);
985 return NULL;
986 }
987 hexchars += neg + 2; /* skip sign and "0x" */
988 mp_init(&bigValue);
989 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
990 mp_clear(&bigValue);
991 Py_DECREF(hexstr);
992 PyErr_NoMemory();
993 return NULL;
994 }
995 Py_DECREF(hexstr);
996 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
997 result = Tcl_NewBignumObj(&bigValue);
998 mp_clear(&bigValue);
999 if (result == NULL) {
1000 PyErr_NoMemory();
1001 return NULL;
1002 }
1003 return result;
1004}
1005#endif
1006
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001007static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001008AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001009{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001010 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001011
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001012 if (PyBytes_Check(value)) {
1013 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
1014 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1015 return NULL;
1016 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +03001017 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001018 (int)PyBytes_GET_SIZE(value));
1019 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001020
1021 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001022 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001023
1024 if (PyLong_CheckExact(value)) {
1025 int overflow;
1026 long longValue;
1027#ifdef TCL_WIDE_INT_TYPE
1028 Tcl_WideInt wideValue;
1029#endif
1030 longValue = PyLong_AsLongAndOverflow(value, &overflow);
1031 if (!overflow) {
1032 return Tcl_NewLongObj(longValue);
1033 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001034 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001035 fall through to wideInt handling. */
1036#ifdef TCL_WIDE_INT_TYPE
1037 if (_PyLong_AsByteArray((PyLongObject *)value,
1038 (unsigned char *)(void *)&wideValue,
1039 sizeof(wideValue),
1040 PY_LITTLE_ENDIAN,
1041 /* signed */ 1) == 0) {
1042 return Tcl_NewWideIntObj(wideValue);
1043 }
1044 PyErr_Clear();
1045#endif
1046 /* If there is an overflow in the wideInt conversion,
1047 fall through to bignum handling. */
Andrew York003708b2020-05-15 03:43:58 -07001048#ifdef HAVE_LIBTOMMATH
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001049 return asBignumObj(value);
1050#endif
1051 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001052 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001053 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001054
1055 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001056 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001057
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +03001058 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001059 Tcl_Obj **argv;
1060 Py_ssize_t size, i;
1061
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001062 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001063 if (size == 0)
1064 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001065 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001066 PyErr_SetString(PyExc_OverflowError,
1067 PyTuple_Check(value) ? "tuple is too long" :
1068 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001069 return NULL;
1070 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001071 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
1072 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001073 PyErr_NoMemory();
1074 return NULL;
1075 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001076 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001077 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001078 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001079 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001080 return result;
1081 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001082
1083 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001084 if (PyUnicode_READY(value) == -1)
1085 return NULL;
1086
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001087 Py_ssize_t size = PyUnicode_GET_LENGTH(value);
1088 if (size == 0) {
1089 return Tcl_NewStringObj("", 0);
1090 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001091 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1092 PyErr_SetString(PyExc_OverflowError, "string is too long");
1093 return NULL;
1094 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001095 if (PyUnicode_IS_ASCII(value)) {
1096 return Tcl_NewStringObj((const char *)PyUnicode_DATA(value),
1097 (int)size);
1098 }
1099
1100 PyObject *encoded;
1101#if USE_TCL_UNICODE
1102 if (sizeof(Tcl_UniChar) == 2)
1103 encoded = _PyUnicode_EncodeUTF16(value,
1104 "surrogatepass", NATIVE_BYTEORDER);
1105 else if (sizeof(Tcl_UniChar) == 4)
1106 encoded = _PyUnicode_EncodeUTF32(value,
1107 "surrogatepass", NATIVE_BYTEORDER);
1108 else
1109 Py_UNREACHABLE();
1110#else
1111 encoded = _PyUnicode_AsUTF8String(value, "surrogateescape");
1112#endif
1113 if (!encoded) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001114 return NULL;
1115 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001116 size = PyBytes_GET_SIZE(encoded);
1117 if (size > INT_MAX) {
1118 Py_DECREF(encoded);
1119 PyErr_SetString(PyExc_OverflowError, "string is too long");
1120 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001121 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001122#if USE_TCL_UNICODE
1123 result = Tcl_NewUnicodeObj((const Tcl_UniChar *)PyBytes_AS_STRING(encoded),
1124 (int)(size / sizeof(Tcl_UniChar)));
1125#else
1126 result = Tcl_NewStringObj(PyBytes_AS_STRING(encoded), (int)size);
1127#endif
1128 Py_DECREF(encoded);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001129 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001130 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001131
1132 if (PyTclObject_Check(value)) {
Serhiy Storchakadf13df42018-10-23 22:40:54 +03001133 return ((PyTclObject*)value)->value;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001134 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001135
1136 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001137 PyObject *v = PyObject_Str(value);
1138 if (!v)
1139 return 0;
1140 result = AsObj(v);
1141 Py_DECREF(v);
1142 return result;
1143 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001144}
1145
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001146static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001147fromBoolean(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001148{
1149 int boolValue;
1150 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1151 return Tkinter_Error(tkapp);
1152 return PyBool_FromLong(boolValue);
1153}
1154
Martin v. Löwisffad6332002-11-26 09:28:05 +00001155static PyObject*
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001156fromWideIntObj(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001157{
1158 Tcl_WideInt wideValue;
1159 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001160 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1161 return PyLong_FromLongLong(wideValue);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001162 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1163 sizeof(wideValue),
1164 PY_LITTLE_ENDIAN,
1165 /* signed */ 1);
1166 }
1167 return NULL;
1168}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001169
Andrew York003708b2020-05-15 03:43:58 -07001170#ifdef HAVE_LIBTOMMATH
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001171static PyObject*
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001172fromBignumObj(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001173{
1174 mp_int bigValue;
1175 unsigned long numBytes;
1176 unsigned char *bytes;
1177 PyObject *res;
1178
1179 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1180 return Tkinter_Error(tkapp);
1181 numBytes = mp_unsigned_bin_size(&bigValue);
1182 bytes = PyMem_Malloc(numBytes);
1183 if (bytes == NULL) {
1184 mp_clear(&bigValue);
1185 return PyErr_NoMemory();
1186 }
1187 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1188 &numBytes) != MP_OKAY) {
1189 mp_clear(&bigValue);
1190 PyMem_Free(bytes);
1191 return PyErr_NoMemory();
1192 }
1193 res = _PyLong_FromByteArray(bytes, numBytes,
1194 /* big-endian */ 0,
1195 /* unsigned */ 0);
1196 PyMem_Free(bytes);
1197 if (res != NULL && bigValue.sign == MP_NEG) {
1198 PyObject *res2 = PyNumber_Negative(res);
1199 Py_DECREF(res);
1200 res = res2;
1201 }
1202 mp_clear(&bigValue);
1203 return res;
1204}
1205#endif
1206
Martin v. Löwisffad6332002-11-26 09:28:05 +00001207static PyObject*
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001208FromObj(TkappObject *tkapp, Tcl_Obj *value)
Martin v. Löwisffad6332002-11-26 09:28:05 +00001209{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001210 PyObject *result = NULL;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001211 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001212
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001213 if (value->typePtr == NULL) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001214 return unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001215 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001216
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001217 if (value->typePtr == tkapp->BooleanType ||
1218 value->typePtr == tkapp->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001219 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001220 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001221
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001222 if (value->typePtr == tkapp->ByteArrayType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001223 int size;
1224 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1225 return PyBytes_FromStringAndSize(data, size);
1226 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001227
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001228 if (value->typePtr == tkapp->DoubleType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001229 return PyFloat_FromDouble(value->internalRep.doubleValue);
1230 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001231
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001232 if (value->typePtr == tkapp->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001233 long longValue;
1234 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1235 return PyLong_FromLong(longValue);
1236 /* If there is an error in the long conversion,
1237 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001238 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001239
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001240 if (value->typePtr == tkapp->IntType ||
1241 value->typePtr == tkapp->WideIntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001242 result = fromWideIntObj(tkapp, value);
1243 if (result != NULL || PyErr_Occurred())
1244 return result;
1245 Tcl_ResetResult(interp);
1246 /* If there is an error in the wideInt conversion,
1247 fall through to bignum handling. */
1248 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001249
Andrew York003708b2020-05-15 03:43:58 -07001250#ifdef HAVE_LIBTOMMATH
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001251 if (value->typePtr == tkapp->IntType ||
1252 value->typePtr == tkapp->WideIntType ||
1253 value->typePtr == tkapp->BignumType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001254 return fromBignumObj(tkapp, value);
1255 }
1256#endif
1257
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001258 if (value->typePtr == tkapp->ListType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001259 int size;
1260 int i, status;
1261 PyObject *elem;
1262 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001263
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001264 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001265 if (status == TCL_ERROR)
1266 return Tkinter_Error(tkapp);
1267 result = PyTuple_New(size);
1268 if (!result)
1269 return NULL;
1270 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001271 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001272 if (status == TCL_ERROR) {
1273 Py_DECREF(result);
1274 return Tkinter_Error(tkapp);
1275 }
1276 elem = FromObj(tkapp, tcl_elem);
1277 if (!elem) {
1278 Py_DECREF(result);
1279 return NULL;
1280 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001281 PyTuple_SET_ITEM(result, i, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001282 }
1283 return result;
1284 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001285
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001286 if (value->typePtr == tkapp->ProcBodyType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001287 /* fall through: return tcl object. */
1288 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001289
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001290 if (value->typePtr == tkapp->StringType) {
1291 return unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001292 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001293
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001294#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001295 if (tkapp->BooleanType == NULL &&
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001296 strcmp(value->typePtr->name, "booleanString") == 0) {
1297 /* booleanString type is not registered in Tcl */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001298 tkapp->BooleanType = value->typePtr;
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001299 return fromBoolean(tkapp, value);
1300 }
1301#endif
1302
Andrew York003708b2020-05-15 03:43:58 -07001303#ifdef HAVE_LIBTOMMATH
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001304 if (tkapp->BignumType == NULL &&
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001305 strcmp(value->typePtr->name, "bignum") == 0) {
1306 /* bignum type is not registered in Tcl */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001307 tkapp->BignumType = value->typePtr;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001308 return fromBignumObj(tkapp, value);
1309 }
1310#endif
1311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001312 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001313}
1314
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001315/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001316TCL_DECLARE_MUTEX(call_mutex)
1317
1318typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001319 Tcl_Event ev; /* Must be first */
1320 TkappObject *self;
1321 PyObject *args;
1322 int flags;
1323 PyObject **res;
1324 PyObject **exc_type, **exc_value, **exc_tb;
1325 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001326} Tkapp_CallEvent;
1327
1328void
1329Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001330{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001331 int i;
1332 for (i = 0; i < objc; i++)
1333 Tcl_DecrRefCount(objv[i]);
1334 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001335 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001336}
Guido van Rossum18468821994-06-20 07:49:28 +00001337
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001338/* Convert Python objects to Tcl objects. This must happen in the
1339 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001340
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001341static Tcl_Obj**
1342Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1343{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001344 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001345 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 if (args == NULL)
1347 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001348
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001349 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 objv[0] = AsObj(args);
Serhiy Storchaka0b3ec192017-03-23 17:53:47 +02001351 if (objv[0] == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 goto finally;
1353 objc = 1;
1354 Tcl_IncrRefCount(objv[0]);
1355 }
1356 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001357 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001358
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001359 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001360 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001361 PyErr_SetString(PyExc_OverflowError,
1362 PyTuple_Check(args) ? "tuple is too long" :
1363 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001364 return NULL;
1365 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001366 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001367 if (objv == NULL) {
1368 PyErr_NoMemory();
1369 objc = 0;
1370 goto finally;
1371 }
1372 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001373
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001374 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001375 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001376 if (v == Py_None) {
1377 objc = i;
1378 break;
1379 }
1380 objv[i] = AsObj(v);
1381 if (!objv[i]) {
1382 /* Reset objc, so it attempts to clear
1383 objects only up to i. */
1384 objc = i;
1385 goto finally;
1386 }
1387 Tcl_IncrRefCount(objv[i]);
1388 }
1389 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001390 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001391 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001392finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001393 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001394 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001395}
Guido van Rossum212643f1998-04-29 16:22:14 +00001396
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001397/* Convert the results of a command call into a Python string. */
1398
1399static PyObject *
1400Tkapp_UnicodeResult(TkappObject *self)
1401{
1402 return unicodeFromTclObj(Tcl_GetObjResult(self->interp));
1403}
1404
1405
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001406/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001407
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001408static PyObject *
1409Tkapp_ObjectResult(TkappObject *self)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001410{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001411 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001412 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001413 if (self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001414 /* Not sure whether the IncrRef is necessary, but something
1415 may overwrite the interpreter result while we are
1416 converting it. */
1417 Tcl_IncrRefCount(value);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001418 res = FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001419 Tcl_DecrRefCount(value);
1420 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001421 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001422 }
1423 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001424}
Guido van Rossum632de272000-03-29 00:19:50 +00001425
Benjamin Peterson5879d412009-03-30 14:51:56 +00001426
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001427/* Tkapp_CallProc is the event procedure that is executed in the context of
1428 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1429 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001430
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001431static int
1432Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1433{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001434 Tcl_Obj *objStore[ARGSZ];
1435 Tcl_Obj **objv;
1436 int objc;
1437 int i;
1438 ENTER_PYTHON
1439 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1440 if (!objv) {
1441 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1442 *(e->res) = NULL;
1443 }
1444 LEAVE_PYTHON
1445 if (!objv)
1446 goto done;
1447 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1448 ENTER_PYTHON
1449 if (i == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001450 *(e->res) = Tkinter_Error(e->self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001451 }
1452 else {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001453 *(e->res) = Tkapp_ObjectResult(e->self);
1454 }
1455 if (*(e->res) == NULL) {
1456 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001457 }
1458 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001459
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001460 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001461done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001462 /* Wake up calling thread. */
1463 Tcl_MutexLock(&call_mutex);
1464 Tcl_ConditionNotify(e->done);
1465 Tcl_MutexUnlock(&call_mutex);
1466 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001467}
1468
Benjamin Peterson5879d412009-03-30 14:51:56 +00001469
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001470/* This is the main entry point for calling a Tcl command.
1471 It supports three cases, with regard to threading:
1472 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1473 the context of the calling thread.
1474 2. Tcl is threaded, caller of the command is in the interpreter thread:
1475 Execute the command in the calling thread. Since the Tcl lock will
1476 not be used, we can merge that with case 1.
1477 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1478 the interpreter thread. Allocation of Tcl objects needs to occur in the
1479 interpreter thread, so we ship the PyObject* args to the target thread,
1480 and perform processing there. */
1481
1482static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001483Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001484{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001485 Tcl_Obj *objStore[ARGSZ];
1486 Tcl_Obj **objv = NULL;
1487 int objc, i;
1488 PyObject *res = NULL;
1489 TkappObject *self = (TkappObject*)selfptr;
1490 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001491
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001492 /* If args is a single tuple, replace with contents of tuple */
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001493 if (PyTuple_GET_SIZE(args) == 1) {
1494 PyObject *item = PyTuple_GET_ITEM(args, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001495 if (PyTuple_Check(item))
1496 args = item;
1497 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001498 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1499 /* We cannot call the command directly. Instead, we must
1500 marshal the parameters to the interpreter thread. */
1501 Tkapp_CallEvent *ev;
1502 Tcl_Condition cond = NULL;
1503 PyObject *exc_type, *exc_value, *exc_tb;
1504 if (!WaitForMainloop(self))
1505 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001506 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1507 if (ev == NULL) {
1508 PyErr_NoMemory();
1509 return NULL;
1510 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001511 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1512 ev->self = self;
1513 ev->args = args;
1514 ev->res = &res;
1515 ev->exc_type = &exc_type;
1516 ev->exc_value = &exc_value;
1517 ev->exc_tb = &exc_tb;
1518 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001519
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001520 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001521
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001522 if (res == NULL) {
1523 if (exc_type)
1524 PyErr_Restore(exc_type, exc_value, exc_tb);
1525 else
1526 PyErr_SetObject(Tkinter_TclError, exc_value);
1527 }
1528 Tcl_ConditionFinalize(&cond);
1529 }
1530 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001531 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001532
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 objv = Tkapp_CallArgs(args, objStore, &objc);
1534 if (!objv)
1535 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001537 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001539 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001542
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001543 if (i == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001544 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001545 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001546 res = Tkapp_ObjectResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001548 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001549
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 Tkapp_CallDeallocArgs(objv, objStore, objc);
1551 }
1552 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001553}
1554
1555
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001556/*[clinic input]
1557_tkinter.tkapp.eval
1558
1559 script: str
1560 /
1561
1562[clinic start generated code]*/
1563
Barry Warsawfa701a81997-01-16 00:15:11 +00001564static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001565_tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1566/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001567{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 PyObject *res = NULL;
1569 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001570
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001571 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001572 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001573
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001574 ENTER_TCL
1575 err = Tcl_Eval(Tkapp_Interp(self), script);
1576 ENTER_OVERLAP
1577 if (err == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001578 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001579 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001580 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001581 LEAVE_OVERLAP_TCL
1582 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001583}
1584
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001585/*[clinic input]
1586_tkinter.tkapp.evalfile
1587
1588 fileName: str
1589 /
1590
1591[clinic start generated code]*/
1592
Guido van Rossum18468821994-06-20 07:49:28 +00001593static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001594_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1595/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001596{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001597 PyObject *res = NULL;
1598 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001599
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001600 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001601 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001602
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001603 ENTER_TCL
1604 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1605 ENTER_OVERLAP
1606 if (err == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001607 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001608 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001609 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001610 LEAVE_OVERLAP_TCL
1611 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001612}
1613
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001614/*[clinic input]
1615_tkinter.tkapp.record
1616
1617 script: str
1618 /
1619
1620[clinic start generated code]*/
1621
Guido van Rossum18468821994-06-20 07:49:28 +00001622static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001623_tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1624/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001625{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001626 PyObject *res = NULL;
1627 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001628
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001629 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001630 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001632 ENTER_TCL
1633 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1634 ENTER_OVERLAP
1635 if (err == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001636 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001637 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001638 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001639 LEAVE_OVERLAP_TCL
1640 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001641}
1642
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001643/*[clinic input]
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001644_tkinter.tkapp.adderrorinfo
Guido van Rossum18468821994-06-20 07:49:28 +00001645
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001646 msg: str
1647 /
1648
1649[clinic start generated code]*/
1650
1651static PyObject *
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001652_tkinter_tkapp_adderrorinfo_impl(TkappObject *self, const char *msg)
1653/*[clinic end generated code: output=52162eaca2ee53cb input=f4b37aec7c7e8c77]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001654{
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001655 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001656 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001658 ENTER_TCL
1659 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1660 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001661
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001662 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001663}
1664
Barry Warsawfa701a81997-01-16 00:15:11 +00001665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001666
Guido van Rossum18468821994-06-20 07:49:28 +00001667/** Tcl Variable **/
1668
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001669typedef PyObject* (*EventFunc)(TkappObject *, PyObject *, int);
Benjamin Peterson5879d412009-03-30 14:51:56 +00001670
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001671TCL_DECLARE_MUTEX(var_mutex)
1672
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001673typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001674 Tcl_Event ev; /* must be first */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001675 TkappObject *self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001676 PyObject *args;
1677 int flags;
1678 EventFunc func;
1679 PyObject **res;
1680 PyObject **exc_type;
1681 PyObject **exc_val;
1682 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001683} VarEvent;
1684
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001685/*[python]
1686
1687class varname_converter(CConverter):
1688 type = 'const char *'
1689 converter = 'varname_converter'
1690
1691[python]*/
1692/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1693
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001694static int
1695varname_converter(PyObject *in, void *_out)
1696{
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +02001697 const char *s;
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001698 const char **out = (const char**)_out;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001699 if (PyBytes_Check(in)) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001700 if (PyBytes_GET_SIZE(in) > INT_MAX) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001701 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1702 return 0;
1703 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001704 s = PyBytes_AS_STRING(in);
1705 if (strlen(s) != (size_t)PyBytes_GET_SIZE(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001706 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001707 return 0;
1708 }
1709 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001710 return 1;
1711 }
1712 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001713 Py_ssize_t size;
1714 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001715 if (s == NULL) {
1716 return 0;
1717 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001718 if (size > INT_MAX) {
1719 PyErr_SetString(PyExc_OverflowError, "string is too long");
1720 return 0;
1721 }
Victor Stinner706768c2014-08-16 01:03:39 +02001722 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001723 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001724 return 0;
1725 }
1726 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001727 return 1;
1728 }
1729 if (PyTclObject_Check(in)) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001730 *out = Tcl_GetString(((PyTclObject *)in)->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001731 return 1;
1732 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001733 PyErr_Format(PyExc_TypeError,
1734 "must be str, bytes or Tcl_Obj, not %.50s",
Victor Stinnerdaa97562020-02-07 03:37:06 +01001735 Py_TYPE(in)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001736 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001737}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001738
Benjamin Peterson5879d412009-03-30 14:51:56 +00001739
Martin v. Löwis59683e82008-06-13 07:50:45 +00001740static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001741var_perform(VarEvent *ev)
1742{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001743 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1744 if (!*(ev->res)) {
1745 PyObject *exc, *val, *tb;
1746 PyErr_Fetch(&exc, &val, &tb);
1747 PyErr_NormalizeException(&exc, &val, &tb);
1748 *(ev->exc_type) = exc;
1749 *(ev->exc_val) = val;
Serhiy Storchaka3ec5f422016-10-28 12:14:34 +03001750 Py_XDECREF(tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001751 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001752
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001753}
1754
1755static int
1756var_proc(VarEvent* ev, int flags)
1757{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001758 ENTER_PYTHON
1759 var_perform(ev);
1760 Tcl_MutexLock(&var_mutex);
1761 Tcl_ConditionNotify(ev->cond);
1762 Tcl_MutexUnlock(&var_mutex);
1763 LEAVE_PYTHON
1764 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001765}
1766
Benjamin Peterson5879d412009-03-30 14:51:56 +00001767
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001768static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001769var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001770{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001771 TkappObject *self = (TkappObject*)selfptr;
1772 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001773 VarEvent *ev;
1774 PyObject *res, *exc_type, *exc_val;
1775 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001776
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001777 /* The current thread is not the interpreter thread. Marshal
1778 the call to the interpreter thread, then wait for
1779 completion. */
1780 if (!WaitForMainloop(self))
1781 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001782
Serhiy Storchaka07940882014-09-11 10:38:54 +03001783 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1784 if (ev == NULL) {
1785 PyErr_NoMemory();
1786 return NULL;
1787 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001788 ev->self = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001789 ev->args = args;
1790 ev->flags = flags;
1791 ev->func = func;
1792 ev->res = &res;
1793 ev->exc_type = &exc_type;
1794 ev->exc_val = &exc_val;
1795 ev->cond = &cond;
1796 ev->ev.proc = (Tcl_EventProc*)var_proc;
1797 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1798 Tcl_ConditionFinalize(&cond);
1799 if (!res) {
1800 PyErr_SetObject(exc_type, exc_val);
1801 Py_DECREF(exc_type);
1802 Py_DECREF(exc_val);
1803 return NULL;
1804 }
1805 return res;
1806 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001807 /* Tcl is not threaded, or this is the interpreter thread. */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001808 return func(self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001809}
1810
Guido van Rossum18468821994-06-20 07:49:28 +00001811static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001812SetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001813{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001814 const char *name1, *name2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001815 PyObject *newValue;
1816 PyObject *res = NULL;
1817 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001818
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001819 switch (PyTuple_GET_SIZE(args)) {
1820 case 2:
1821 if (!PyArg_ParseTuple(args, "O&O:setvar",
1822 varname_converter, &name1, &newValue))
1823 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001824 /* XXX Acquire tcl lock??? */
1825 newval = AsObj(newValue);
1826 if (newval == NULL)
1827 return NULL;
1828 ENTER_TCL
1829 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1830 newval, flags);
1831 ENTER_OVERLAP
1832 if (!ok)
1833 Tkinter_Error(self);
1834 else {
1835 res = Py_None;
1836 Py_INCREF(res);
1837 }
1838 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001839 break;
1840 case 3:
1841 if (!PyArg_ParseTuple(args, "ssO:setvar",
1842 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001843 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001844 CHECK_STRING_LENGTH(name1);
1845 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001846 /* XXX must hold tcl lock already??? */
1847 newval = AsObj(newValue);
1848 ENTER_TCL
1849 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1850 ENTER_OVERLAP
1851 if (!ok)
1852 Tkinter_Error(self);
1853 else {
1854 res = Py_None;
1855 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001856 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001857 LEAVE_OVERLAP_TCL
1858 break;
1859 default:
1860 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1861 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001862 }
1863 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001864}
1865
1866static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001867Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001868{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001869 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001870}
1871
1872static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001873Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001874{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001875 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001876}
1877
Barry Warsawfa701a81997-01-16 00:15:11 +00001878
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001879
Guido van Rossum18468821994-06-20 07:49:28 +00001880static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001881GetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001882{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001883 const char *name1, *name2=NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001884 PyObject *res = NULL;
1885 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001886
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001887 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1888 varname_converter, &name1, &name2))
1889 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001890
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001891 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001892 ENTER_TCL
1893 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1894 ENTER_OVERLAP
1895 if (tres == NULL) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001896 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001897 } else {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001898 if (self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001899 res = FromObj(self, tres);
1900 }
1901 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001902 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001903 }
1904 }
1905 LEAVE_OVERLAP_TCL
1906 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001907}
1908
1909static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001910Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001911{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001912 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001913}
1914
1915static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001916Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001917{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001918 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001919}
1920
Barry Warsawfa701a81997-01-16 00:15:11 +00001921
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001922
Guido van Rossum18468821994-06-20 07:49:28 +00001923static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001924UnsetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001925{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001926 char *name1, *name2=NULL;
1927 int code;
1928 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001929
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001930 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1931 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001932
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001933 CHECK_STRING_LENGTH(name1);
1934 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001935 ENTER_TCL
1936 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1937 ENTER_OVERLAP
1938 if (code == TCL_ERROR)
1939 res = Tkinter_Error(self);
1940 else {
1941 Py_INCREF(Py_None);
1942 res = Py_None;
1943 }
1944 LEAVE_OVERLAP_TCL
1945 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001946}
1947
1948static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001949Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001950{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001951 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001952}
1953
1954static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001955Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001956{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001957 return var_invoke(UnsetVar, self, args,
1958 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001959}
1960
Barry Warsawfa701a81997-01-16 00:15:11 +00001961
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001962
Guido van Rossum18468821994-06-20 07:49:28 +00001963/** Tcl to Python **/
1964
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001965/*[clinic input]
1966_tkinter.tkapp.getint
1967
1968 arg: object
1969 /
1970
1971[clinic start generated code]*/
1972
Guido van Rossum18468821994-06-20 07:49:28 +00001973static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001974_tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
1975/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001976{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001977 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001978 Tcl_Obj *value;
1979 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00001980
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001981 if (PyLong_Check(arg)) {
1982 Py_INCREF(arg);
1983 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001984 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001985
Serhiy Storchaka645058d2015-05-06 14:00:04 +03001986 if (PyTclObject_Check(arg)) {
1987 value = ((PyTclObject*)arg)->value;
1988 Tcl_IncrRefCount(value);
1989 }
1990 else {
1991 if (!PyArg_Parse(arg, "s:getint", &s))
1992 return NULL;
1993 CHECK_STRING_LENGTH(s);
1994 value = Tcl_NewStringObj(s, -1);
1995 if (value == NULL)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001996 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03001997 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001998 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
1999 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
2000
2001 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
2002 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
2003 */
Andrew York003708b2020-05-15 03:43:58 -07002004#ifdef HAVE_LIBTOMMATH
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002005 result = fromBignumObj(self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002006#else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002007 result = fromWideIntObj(self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002008#endif
2009 Tcl_DecrRefCount(value);
2010 if (result != NULL || PyErr_Occurred())
2011 return result;
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002012 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00002013}
2014
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002015/*[clinic input]
2016_tkinter.tkapp.getdouble
2017
2018 arg: object
2019 /
2020
2021[clinic start generated code]*/
2022
Guido van Rossum18468821994-06-20 07:49:28 +00002023static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002024_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
2025/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002026{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002027 char *s;
2028 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00002029
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002030 if (PyFloat_Check(arg)) {
2031 Py_INCREF(arg);
2032 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002033 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002034
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002035 if (PyNumber_Check(arg)) {
2036 return PyNumber_Float(arg);
2037 }
2038
2039 if (PyTclObject_Check(arg)) {
2040 if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
2041 ((PyTclObject*)arg)->value,
2042 &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002043 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002044 return PyFloat_FromDouble(v);
2045 }
2046
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002047 if (!PyArg_Parse(arg, "s:getdouble", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002048 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002049 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002050 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002051 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002052 return PyFloat_FromDouble(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002053}
2054
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002055/*[clinic input]
2056_tkinter.tkapp.getboolean
2057
2058 arg: object
2059 /
2060
2061[clinic start generated code]*/
2062
Guido van Rossum18468821994-06-20 07:49:28 +00002063static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002064_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
2065/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002066{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002067 char *s;
2068 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002069
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002070 if (PyLong_Check(arg)) { /* int or bool */
2071 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002072 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002073
2074 if (PyTclObject_Check(arg)) {
2075 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2076 ((PyTclObject*)arg)->value,
2077 &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002078 return Tkinter_Error(self);
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002079 return PyBool_FromLong(v);
2080 }
2081
2082 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002083 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002084 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002085 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002086 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002087 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002088}
2089
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002090/*[clinic input]
2091_tkinter.tkapp.exprstring
2092
2093 s: str
2094 /
2095
2096[clinic start generated code]*/
2097
Guido van Rossum18468821994-06-20 07:49:28 +00002098static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002099_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2100/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002101{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002102 PyObject *res = NULL;
2103 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002104
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002105 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002106 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002107
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002108 ENTER_TCL
2109 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2110 ENTER_OVERLAP
2111 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002112 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002113 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002114 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115 LEAVE_OVERLAP_TCL
2116 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002117}
2118
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002119/*[clinic input]
2120_tkinter.tkapp.exprlong
2121
2122 s: str
2123 /
2124
2125[clinic start generated code]*/
2126
Guido van Rossum18468821994-06-20 07:49:28 +00002127static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002128_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2129/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002130{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002131 PyObject *res = NULL;
2132 int retval;
2133 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002134
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002135 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002136 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002137
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 ENTER_TCL
2139 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2140 ENTER_OVERLAP
2141 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002142 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002143 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002144 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002145 LEAVE_OVERLAP_TCL
2146 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002147}
2148
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002149/*[clinic input]
2150_tkinter.tkapp.exprdouble
2151
2152 s: str
2153 /
2154
2155[clinic start generated code]*/
2156
Guido van Rossum18468821994-06-20 07:49:28 +00002157static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002158_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2159/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002160{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002161 PyObject *res = NULL;
2162 double v;
2163 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002164
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002165 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002166 CHECK_TCL_APPARTMENT;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002167 ENTER_TCL
2168 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2169 ENTER_OVERLAP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002170 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002171 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002172 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002173 res = PyFloat_FromDouble(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002174 LEAVE_OVERLAP_TCL
2175 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002176}
2177
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002178/*[clinic input]
2179_tkinter.tkapp.exprboolean
2180
2181 s: str
2182 /
2183
2184[clinic start generated code]*/
2185
Guido van Rossum18468821994-06-20 07:49:28 +00002186static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002187_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2188/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002189{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002190 PyObject *res = NULL;
2191 int retval;
2192 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002193
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002194 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002195 CHECK_TCL_APPARTMENT;
2196 ENTER_TCL
2197 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2198 ENTER_OVERLAP
2199 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002200 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002201 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002202 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002203 LEAVE_OVERLAP_TCL
2204 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002205}
2206
Barry Warsawfa701a81997-01-16 00:15:11 +00002207
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002208
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002209/*[clinic input]
2210_tkinter.tkapp.splitlist
2211
2212 arg: object
2213 /
2214
2215[clinic start generated code]*/
2216
Guido van Rossum18468821994-06-20 07:49:28 +00002217static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002218_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2219/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002220{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002221 char *list;
2222 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002223 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002224 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002225 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002226
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002227 if (PyTclObject_Check(arg)) {
2228 int objc;
2229 Tcl_Obj **objv;
2230 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2231 ((PyTclObject*)arg)->value,
2232 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002233 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002234 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002235 if (!(v = PyTuple_New(objc)))
2236 return NULL;
2237 for (i = 0; i < objc; i++) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002238 PyObject *s = FromObj(self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002239 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002240 Py_DECREF(v);
2241 return NULL;
2242 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002243 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002244 }
2245 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002246 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002247 if (PyTuple_Check(arg)) {
2248 Py_INCREF(arg);
2249 return arg;
2250 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002251 if (PyList_Check(arg)) {
2252 return PySequence_Tuple(arg);
2253 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002254
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002255 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002256 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002257
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002258 if (strlen(list) >= INT_MAX) {
2259 PyErr_SetString(PyExc_OverflowError, "string is too long");
2260 PyMem_Free(list);
2261 return NULL;
2262 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002263 if (Tcl_SplitList(Tkapp_Interp(self), list,
2264 &argc, &argv) == TCL_ERROR) {
2265 PyMem_Free(list);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002266 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002267 }
Guido van Rossum18468821994-06-20 07:49:28 +00002268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002269 if (!(v = PyTuple_New(argc)))
2270 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002271
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002272 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002273 PyObject *s = unicodeFromTclString(argv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002274 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002275 Py_DECREF(v);
2276 v = NULL;
2277 goto finally;
2278 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002279 PyTuple_SET_ITEM(v, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002280 }
Guido van Rossum18468821994-06-20 07:49:28 +00002281
Barry Warsawfa701a81997-01-16 00:15:11 +00002282 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002283 ckfree(FREECAST argv);
2284 PyMem_Free(list);
2285 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002286}
2287
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002288/*[clinic input]
2289_tkinter.tkapp.split
2290
2291 arg: object
2292 /
2293
2294[clinic start generated code]*/
2295
Guido van Rossum18468821994-06-20 07:49:28 +00002296static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002297_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2298/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002299{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002300 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002301 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002302
Serhiy Storchakad05b0002019-10-08 14:31:35 +03002303 if (PyErr_WarnEx(PyExc_DeprecationWarning,
2304 "split() is deprecated; consider using splitlist() instead", 1))
2305 {
2306 return NULL;
2307 }
2308
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002309 if (PyTclObject_Check(arg)) {
2310 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2311 int objc;
2312 Tcl_Obj **objv;
2313 int i;
2314 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2315 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002316 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002317 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002318 if (objc == 0)
2319 return PyUnicode_FromString("");
2320 if (objc == 1)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002321 return FromObj(self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002322 if (!(v = PyTuple_New(objc)))
2323 return NULL;
2324 for (i = 0; i < objc; i++) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002325 PyObject *s = FromObj(self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002326 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002327 Py_DECREF(v);
2328 return NULL;
2329 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002330 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002331 }
2332 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002333 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002334 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002335 return SplitObj(arg);
2336
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002337 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002338 return NULL;
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002339 if (strlen(list) >= INT_MAX) {
2340 PyErr_SetString(PyExc_OverflowError, "string is too long");
2341 PyMem_Free(list);
2342 return NULL;
2343 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002344 v = Split(list);
2345 PyMem_Free(list);
2346 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002347}
2348
Barry Warsawfa701a81997-01-16 00:15:11 +00002349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002350
Guido van Rossum18468821994-06-20 07:49:28 +00002351/** Tcl Command **/
2352
Guido van Rossum00d93061998-05-28 23:06:38 +00002353/* Client data struct */
2354typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002355 PyObject *self;
2356 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002357} PythonCmd_ClientData;
2358
2359static int
Fred Drake509d79a2000-07-08 04:04:38 +00002360PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002361{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002362 errorInCmd = 1;
2363 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2364 LEAVE_PYTHON
2365 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002366}
2367
Guido van Rossum18468821994-06-20 07:49:28 +00002368/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002369 * function or method.
2370 */
Guido van Rossum18468821994-06-20 07:49:28 +00002371static int
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002372PythonCmd(ClientData clientData, Tcl_Interp *interp,
2373 int objc, Tcl_Obj *const objv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002374{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002375 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002376 PyObject *args, *res;
2377 int i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002378 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002380 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002381
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002382 /* Create argument tuple (objv1, ..., objvN) */
2383 if (!(args = PyTuple_New(objc - 1)))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002384 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002385
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002386 for (i = 0; i < (objc - 1); i++) {
2387 PyObject *s = unicodeFromTclObj(objv[i + 1]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002388 if (!s) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002389 Py_DECREF(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002390 return PythonCmd_Error(interp);
2391 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002392 PyTuple_SET_ITEM(args, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002393 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002394
2395 res = PyObject_Call(data->func, args, NULL);
2396 Py_DECREF(args);
Guido van Rossum18468821994-06-20 07:49:28 +00002397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002398 if (res == NULL)
2399 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002401 obj_res = AsObj(res);
2402 if (obj_res == NULL) {
2403 Py_DECREF(res);
2404 return PythonCmd_Error(interp);
2405 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002406 Tcl_SetObjResult(interp, obj_res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002409 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002410
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002411 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +00002412}
2413
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002414
Guido van Rossum18468821994-06-20 07:49:28 +00002415static void
Fred Drake509d79a2000-07-08 04:04:38 +00002416PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002417{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002418 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002420 ENTER_PYTHON
2421 Py_XDECREF(data->self);
2422 Py_XDECREF(data->func);
2423 PyMem_DEL(data);
2424 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002425}
2426
Barry Warsawfa701a81997-01-16 00:15:11 +00002427
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002428
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002429
2430TCL_DECLARE_MUTEX(command_mutex)
2431
2432typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002433 Tcl_Event ev;
2434 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002435 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002436 int create;
2437 int *status;
2438 ClientData *data;
2439 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002440} CommandEvent;
2441
2442static int
2443Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002444{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002445 if (ev->create)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002446 *ev->status = Tcl_CreateObjCommand(
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002447 ev->interp, ev->name, PythonCmd,
2448 ev->data, PythonCmdDelete) == NULL;
2449 else
2450 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2451 Tcl_MutexLock(&command_mutex);
2452 Tcl_ConditionNotify(ev->done);
2453 Tcl_MutexUnlock(&command_mutex);
2454 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002455}
2456
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002457/*[clinic input]
2458_tkinter.tkapp.createcommand
2459
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002460 name: str
2461 func: object
2462 /
2463
2464[clinic start generated code]*/
2465
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002466static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002467_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2468 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002469/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002470{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002472 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002473
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002474 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002475 if (!PyCallable_Check(func)) {
2476 PyErr_SetString(PyExc_TypeError, "command not callable");
2477 return NULL;
2478 }
Guido van Rossum18468821994-06-20 07:49:28 +00002479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002480 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2481 !WaitForMainloop(self))
2482 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002484 data = PyMem_NEW(PythonCmd_ClientData, 1);
2485 if (!data)
2486 return PyErr_NoMemory();
2487 Py_INCREF(self);
2488 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002489 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002490 data->func = func;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002491 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2492 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002493 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2494 if (ev == NULL) {
2495 PyErr_NoMemory();
2496 PyMem_DEL(data);
2497 return NULL;
2498 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002499 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2500 ev->interp = self->interp;
2501 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002502 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002503 ev->data = (ClientData)data;
2504 ev->status = &err;
2505 ev->done = &cond;
2506 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2507 Tcl_ConditionFinalize(&cond);
2508 }
2509 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002510 {
2511 ENTER_TCL
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002512 err = Tcl_CreateObjCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002513 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002514 (ClientData)data, PythonCmdDelete) == NULL;
2515 LEAVE_TCL
2516 }
2517 if (err) {
2518 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2519 PyMem_DEL(data);
2520 return NULL;
2521 }
Guido van Rossum18468821994-06-20 07:49:28 +00002522
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002523 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002524}
2525
Barry Warsawfa701a81997-01-16 00:15:11 +00002526
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002527
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002528/*[clinic input]
2529_tkinter.tkapp.deletecommand
2530
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002531 name: str
2532 /
2533
2534[clinic start generated code]*/
2535
Guido van Rossum18468821994-06-20 07:49:28 +00002536static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002537_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002538/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002539{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002540 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002541
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002542 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002543
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002544 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2545 Tcl_Condition cond = NULL;
2546 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002547 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2548 if (ev == NULL) {
2549 PyErr_NoMemory();
2550 return NULL;
2551 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002552 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2553 ev->interp = self->interp;
2554 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002555 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002556 ev->status = &err;
2557 ev->done = &cond;
2558 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2559 &command_mutex);
2560 Tcl_ConditionFinalize(&cond);
2561 }
2562 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002563 {
2564 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002565 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002566 LEAVE_TCL
2567 }
2568 if (err == -1) {
2569 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2570 return NULL;
2571 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002572 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002573}
2574
Barry Warsawfa701a81997-01-16 00:15:11 +00002575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002576
Guido van Rossum00d93061998-05-28 23:06:38 +00002577#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002578/** File Handler **/
2579
Guido van Rossum00d93061998-05-28 23:06:38 +00002580typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002581 PyObject *func;
2582 PyObject *file;
2583 int id;
2584 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002585} FileHandler_ClientData;
2586
2587static FileHandler_ClientData *HeadFHCD;
2588
2589static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002590NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002591{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002592 FileHandler_ClientData *p;
2593 p = PyMem_NEW(FileHandler_ClientData, 1);
2594 if (p != NULL) {
2595 Py_XINCREF(func);
2596 Py_XINCREF(file);
2597 p->func = func;
2598 p->file = file;
2599 p->id = id;
2600 p->next = HeadFHCD;
2601 HeadFHCD = p;
2602 }
2603 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002604}
2605
2606static void
Fred Drake509d79a2000-07-08 04:04:38 +00002607DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002608{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002609 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002611 pp = &HeadFHCD;
2612 while ((p = *pp) != NULL) {
2613 if (p->id == id) {
2614 *pp = p->next;
2615 Py_XDECREF(p->func);
2616 Py_XDECREF(p->file);
2617 PyMem_DEL(p);
2618 }
2619 else
2620 pp = &p->next;
2621 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002622}
2623
Guido van Rossuma597dde1995-01-10 20:56:29 +00002624static void
Fred Drake509d79a2000-07-08 04:04:38 +00002625FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002626{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002627 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
INADA Naoki72dccde2017-02-16 09:26:01 +09002628 PyObject *func, *file, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002629
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002630 ENTER_PYTHON
2631 func = data->func;
2632 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002633
INADA Naoki72dccde2017-02-16 09:26:01 +09002634 res = PyObject_CallFunction(func, "Oi", file, mask);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002635 if (res == NULL) {
2636 errorInCmd = 1;
2637 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2638 }
2639 Py_XDECREF(res);
2640 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002641}
2642
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002643/*[clinic input]
2644_tkinter.tkapp.createfilehandler
2645
2646 file: object
2647 mask: int
2648 func: object
2649 /
2650
2651[clinic start generated code]*/
2652
Guido van Rossum18468821994-06-20 07:49:28 +00002653static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002654_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2655 int mask, PyObject *func)
2656/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002657{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002658 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002659 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002661 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002662
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002663 tfile = PyObject_AsFileDescriptor(file);
2664 if (tfile < 0)
2665 return NULL;
2666 if (!PyCallable_Check(func)) {
2667 PyErr_SetString(PyExc_TypeError, "bad argument list");
2668 return NULL;
2669 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002670
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002671 data = NewFHCD(func, file, tfile);
2672 if (data == NULL)
2673 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002674
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002675 /* Ought to check for null Tcl_File object... */
2676 ENTER_TCL
2677 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2678 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002679 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002680}
2681
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002682/*[clinic input]
2683_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002684
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002685 file: object
2686 /
2687
2688[clinic start generated code]*/
2689
2690static PyObject *
2691_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2692/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2693{
2694 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002696 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002697
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002698 tfile = PyObject_AsFileDescriptor(file);
2699 if (tfile < 0)
2700 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002702 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002703
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002704 /* Ought to check for null Tcl_File object... */
2705 ENTER_TCL
2706 Tcl_DeleteFileHandler(tfile);
2707 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002708 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002709}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002710#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002711
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002712
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002713/**** Tktt Object (timer token) ****/
2714
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002715static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002716
Guido van Rossum00d93061998-05-28 23:06:38 +00002717typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002718 PyObject_HEAD
2719 Tcl_TimerToken token;
2720 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002721} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002722
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002723/*[clinic input]
2724_tkinter.tktimertoken.deletetimerhandler
2725
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002726[clinic start generated code]*/
2727
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002728static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002729_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002730/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002731{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002732 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002733 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002734
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002735 if (v->token != NULL) {
2736 Tcl_DeleteTimerHandler(v->token);
2737 v->token = NULL;
2738 }
2739 if (func != NULL) {
2740 v->func = NULL;
2741 Py_DECREF(func);
2742 Py_DECREF(v); /* See Tktt_New() */
2743 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002744 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002745}
2746
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002747static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002748Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002749{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002750 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002751
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002752 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002753 if (v == NULL)
2754 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002755
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002756 Py_INCREF(func);
2757 v->token = NULL;
2758 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002759
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002760 /* Extra reference, deleted when called or when handler is deleted */
2761 Py_INCREF(v);
2762 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002763}
2764
2765static void
Fred Drake509d79a2000-07-08 04:04:38 +00002766Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002767{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002768 TkttObject *v = (TkttObject *)self;
2769 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002770 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002771
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002772 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002773
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002774 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002775 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002776}
2777
Guido van Rossum597ac201998-05-12 14:36:19 +00002778static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002779Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002780{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002781 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002782 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2783 v,
2784 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002785}
2786
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002787/** Timer Handler **/
2788
2789static void
Fred Drake509d79a2000-07-08 04:04:38 +00002790TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002791{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002792 TkttObject *v = (TkttObject *)clientData;
2793 PyObject *func = v->func;
2794 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002795
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002796 if (func == NULL)
2797 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002798
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002799 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002800
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002801 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002802
Victor Stinner2ff58a22019-06-17 14:27:23 +02002803 res = PyObject_CallNoArgs(func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002804 Py_DECREF(func);
2805 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002806
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002807 if (res == NULL) {
2808 errorInCmd = 1;
2809 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2810 }
2811 else
2812 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002813
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002814 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002815}
2816
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002817/*[clinic input]
2818_tkinter.tkapp.createtimerhandler
2819
2820 milliseconds: int
2821 func: object
2822 /
2823
2824[clinic start generated code]*/
2825
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002826static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002827_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2828 PyObject *func)
2829/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002830{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002831 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002832
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002833 if (!PyCallable_Check(func)) {
2834 PyErr_SetString(PyExc_TypeError, "bad argument list");
2835 return NULL;
2836 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002837
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002838 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002839
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002840 v = Tktt_New(func);
2841 if (v) {
2842 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2843 (ClientData)v);
2844 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002845
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002846 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002847}
2848
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002849
Guido van Rossum18468821994-06-20 07:49:28 +00002850/** Event Loop **/
2851
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002852/*[clinic input]
2853_tkinter.tkapp.mainloop
2854
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002855 threshold: int = 0
2856 /
2857
2858[clinic start generated code]*/
2859
Guido van Rossum18468821994-06-20 07:49:28 +00002860static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002861_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002862/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002863{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002864 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002865
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002866 CHECK_TCL_APPARTMENT;
2867 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002868
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002869 quitMainLoop = 0;
2870 while (Tk_GetNumMainWindows() > threshold &&
2871 !quitMainLoop &&
2872 !errorInCmd)
2873 {
2874 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002876 if (self->threaded) {
2877 /* Allow other Python threads to run. */
2878 ENTER_TCL
2879 result = Tcl_DoOneEvent(0);
2880 LEAVE_TCL
2881 }
2882 else {
2883 Py_BEGIN_ALLOW_THREADS
2884 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2885 tcl_tstate = tstate;
2886 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2887 tcl_tstate = NULL;
2888 if(tcl_lock)PyThread_release_lock(tcl_lock);
2889 if (result == 0)
2890 Sleep(Tkinter_busywaitinterval);
2891 Py_END_ALLOW_THREADS
2892 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002893
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002894 if (PyErr_CheckSignals() != 0) {
2895 self->dispatching = 0;
2896 return NULL;
2897 }
2898 if (result < 0)
2899 break;
2900 }
2901 self->dispatching = 0;
2902 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002903
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002904 if (errorInCmd) {
2905 errorInCmd = 0;
2906 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2907 excInCmd = valInCmd = trbInCmd = NULL;
2908 return NULL;
2909 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002910 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002911}
2912
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002913/*[clinic input]
2914_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002915
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002916 flags: int = 0
2917 /
2918
2919[clinic start generated code]*/
2920
2921static PyObject *
2922_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2923/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2924{
2925 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002926
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002927 ENTER_TCL
2928 rv = Tcl_DoOneEvent(flags);
2929 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002930 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002931}
2932
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002933/*[clinic input]
2934_tkinter.tkapp.quit
2935[clinic start generated code]*/
2936
Guido van Rossum062cfb01995-01-10 17:42:51 +00002937static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002938_tkinter_tkapp_quit_impl(TkappObject *self)
2939/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002940{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002941 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002942 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002943}
2944
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002945/*[clinic input]
2946_tkinter.tkapp.interpaddr
2947[clinic start generated code]*/
2948
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002949static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002950_tkinter_tkapp_interpaddr_impl(TkappObject *self)
2951/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002952{
Victor Stinnere1040e22013-09-05 00:22:24 +02002953 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002954}
2955
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002956/*[clinic input]
2957_tkinter.tkapp.loadtk
2958[clinic start generated code]*/
2959
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002960static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002961_tkinter_tkapp_loadtk_impl(TkappObject *self)
2962/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00002963{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002964 Tcl_Interp *interp = Tkapp_Interp(self);
2965 const char * _tk_exists = NULL;
2966 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002967
Guilherme Polob681df42009-02-09 22:33:59 +00002968#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002969 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2970 * first call failed.
2971 * To avoid the deadlock, we just refuse the second call through
2972 * a static variable.
2973 */
2974 if (tk_load_failed) {
2975 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2976 return NULL;
2977 }
Guilherme Polob681df42009-02-09 22:33:59 +00002978#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002979
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002980 /* We want to guard against calling Tk_Init() multiple times */
2981 CHECK_TCL_APPARTMENT;
2982 ENTER_TCL
2983 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2984 ENTER_OVERLAP
2985 if (err == TCL_ERROR) {
2986 /* This sets an exception, but we cannot return right
2987 away because we need to exit the overlap first. */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002988 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002989 } else {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002990 _tk_exists = Tcl_GetStringResult(Tkapp_Interp(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002991 }
2992 LEAVE_OVERLAP_TCL
2993 if (err == TCL_ERROR) {
2994 return NULL;
2995 }
2996 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2997 if (Tk_Init(interp) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002998 Tkinter_Error(self);
Guilherme Polob681df42009-02-09 22:33:59 +00002999#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003000 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00003001#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003002 return NULL;
3003 }
3004 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003005 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00003006}
Barry Warsawfa701a81997-01-16 00:15:11 +00003007
Martin v. Löwisffad6332002-11-26 09:28:05 +00003008static PyObject *
3009Tkapp_WantObjects(PyObject *self, PyObject *args)
3010{
3011
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003012 int wantobjects = -1;
3013 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3014 return NULL;
3015 if (wantobjects == -1)
3016 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3017 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003018
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003019 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003020}
3021
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003022/*[clinic input]
3023_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003024
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003025[clinic start generated code]*/
3026
3027static PyObject *
3028_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03003029/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003030{
3031 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003032
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003033 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003034}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003035
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003036
Guido van Rossum18468821994-06-20 07:49:28 +00003037/**** Tkapp Type Methods ****/
3038
3039static void
Fred Drake509d79a2000-07-08 04:04:38 +00003040Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003041{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003042 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003043 /*CHECK_TCL_APPARTMENT;*/
3044 ENTER_TCL
3045 Tcl_DeleteInterp(Tkapp_Interp(self));
3046 LEAVE_TCL
3047 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003048 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003049 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003050}
3051
Barry Warsawfa701a81997-01-16 00:15:11 +00003052
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003053
Guido van Rossum18468821994-06-20 07:49:28 +00003054/**** Tkinter Module ****/
3055
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003056typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003057 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003058 Py_ssize_t size; /* current size */
3059 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003060} FlattenContext;
3061
3062static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003063_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003064{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003065 /* expand tuple to hold (at least) size new items.
3066 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003067
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003068 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003069
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003070 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003071 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003072
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003073 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003074
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003075 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003076}
3077
3078static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003079_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003080{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003081 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003082
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003083 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003084
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003085 if (depth > 1000) {
3086 PyErr_SetString(PyExc_ValueError,
3087 "nesting too deep in _flatten");
3088 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003089 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3090 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003091 /* preallocate (assume no nesting) */
3092 if (context->size + size > context->maxsize &&
3093 !_bump(context, size))
3094 return 0;
3095 /* copy items to output tuple */
3096 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003097 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003098 if (PyList_Check(o) || PyTuple_Check(o)) {
3099 if (!_flatten1(context, o, depth + 1))
3100 return 0;
3101 } else if (o != Py_None) {
3102 if (context->size + 1 > context->maxsize &&
3103 !_bump(context, 1))
3104 return 0;
3105 Py_INCREF(o);
3106 PyTuple_SET_ITEM(context->tuple,
3107 context->size++, o);
3108 }
3109 }
3110 } else {
3111 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3112 return 0;
3113 }
3114 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003115}
3116
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003117/*[clinic input]
3118_tkinter._flatten
3119
3120 item: object
3121 /
3122
3123[clinic start generated code]*/
3124
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003125static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003126_tkinter__flatten(PyObject *module, PyObject *item)
3127/*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003128{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003129 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003130
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003131 context.maxsize = PySequence_Size(item);
3132 if (context.maxsize < 0)
3133 return NULL;
3134 if (context.maxsize == 0)
3135 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003136
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003137 context.tuple = PyTuple_New(context.maxsize);
3138 if (!context.tuple)
3139 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003141 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003142
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003143 if (!_flatten1(&context, item,0))
3144 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003145
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003146 if (_PyTuple_Resize(&context.tuple, context.size))
3147 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003148
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003149 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003150}
3151
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003152/*[clinic input]
3153_tkinter.create
3154
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003155 screenName: str(accept={str, NoneType}) = None
3156 baseName: str = ""
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003157 className: str = "Tk"
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003158 interactive: bool(accept={int}) = False
3159 wantobjects: bool(accept={int}) = False
3160 wantTk: bool(accept={int}) = True
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003161 if false, then Tk_Init() doesn't get called
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003162 sync: bool(accept={int}) = False
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003163 if true, then pass -sync to wish
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003164 use: str(accept={str, NoneType}) = None
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003165 if not None, then pass -use to wish
3166 /
3167
3168[clinic start generated code]*/
3169
Guido van Rossum18468821994-06-20 07:49:28 +00003170static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003171_tkinter_create_impl(PyObject *module, const char *screenName,
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003172 const char *baseName, const char *className,
3173 int interactive, int wantobjects, int wantTk, int sync,
3174 const char *use)
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003175/*[clinic end generated code: output=e3315607648e6bb4 input=da9b17ee7358d862]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003176{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003177 /* XXX baseName is not used anymore;
3178 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003179 CHECK_STRING_LENGTH(screenName);
3180 CHECK_STRING_LENGTH(baseName);
3181 CHECK_STRING_LENGTH(className);
3182 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003183
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003184 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003185 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003186 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003187}
3188
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003189/*[clinic input]
3190_tkinter.setbusywaitinterval
3191
3192 new_val: int
3193 /
3194
3195Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3196
3197It should be set to a divisor of the maximum time between frames in an animation.
3198[clinic start generated code]*/
3199
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003200static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003201_tkinter_setbusywaitinterval_impl(PyObject *module, int new_val)
3202/*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003203{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003204 if (new_val < 0) {
3205 PyErr_SetString(PyExc_ValueError,
3206 "busywaitinterval must be >= 0");
3207 return NULL;
3208 }
3209 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003210 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003211}
3212
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003213/*[clinic input]
3214_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003215
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003216Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3217[clinic start generated code]*/
3218
3219static int
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003220_tkinter_getbusywaitinterval_impl(PyObject *module)
3221/*[clinic end generated code: output=23b72d552001f5c7 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003222{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003223 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003224}
3225
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003226#include "clinic/_tkinter.c.h"
3227
3228static PyMethodDef Tktt_methods[] =
3229{
3230 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3231 {NULL, NULL}
3232};
3233
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003234static PyType_Slot Tktt_Type_slots[] = {
3235 {Py_tp_dealloc, Tktt_Dealloc},
3236 {Py_tp_repr, Tktt_Repr},
3237 {Py_tp_methods, Tktt_methods},
3238 {0, 0}
3239};
3240
3241static PyType_Spec Tktt_Type_spec = {
3242 "_tkinter.tktimertoken",
3243 sizeof(TkttObject),
3244 0,
3245 Py_TPFLAGS_DEFAULT,
3246 Tktt_Type_slots,
3247};
3248
3249
3250/**** Tkapp Method List ****/
3251
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003252static PyMethodDef Tkapp_methods[] =
3253{
3254 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3255 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3256 {"call", Tkapp_Call, METH_VARARGS},
3257 _TKINTER_TKAPP_EVAL_METHODDEF
3258 _TKINTER_TKAPP_EVALFILE_METHODDEF
3259 _TKINTER_TKAPP_RECORD_METHODDEF
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03003260 _TKINTER_TKAPP_ADDERRORINFO_METHODDEF
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003261 {"setvar", Tkapp_SetVar, METH_VARARGS},
3262 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3263 {"getvar", Tkapp_GetVar, METH_VARARGS},
3264 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3265 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3266 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3267 _TKINTER_TKAPP_GETINT_METHODDEF
3268 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3269 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3270 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3271 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3272 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3273 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3274 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3275 _TKINTER_TKAPP_SPLIT_METHODDEF
3276 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3277 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3278 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3279 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3280 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3281 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3282 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3283 _TKINTER_TKAPP_QUIT_METHODDEF
3284 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3285 _TKINTER_TKAPP_LOADTK_METHODDEF
3286 {NULL, NULL}
3287};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003288
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003289static PyType_Slot Tkapp_Type_slots[] = {
3290 {Py_tp_dealloc, Tkapp_Dealloc},
3291 {Py_tp_methods, Tkapp_methods},
3292 {0, 0}
3293};
3294
3295
3296static PyType_Spec Tkapp_Type_spec = {
3297 "_tkinter.tkapp",
3298 sizeof(TkappObject),
3299 0,
3300 Py_TPFLAGS_DEFAULT,
3301 Tkapp_Type_slots,
3302};
3303
Guido van Rossum18468821994-06-20 07:49:28 +00003304static PyMethodDef moduleMethods[] =
3305{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003306 _TKINTER__FLATTEN_METHODDEF
3307 _TKINTER_CREATE_METHODDEF
3308 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3309 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003310 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003311};
3312
Guido van Rossum7bf15641998-05-22 18:28:17 +00003313#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003314
3315static int stdin_ready = 0;
3316
Guido van Rossumad4db171998-06-13 13:56:28 +00003317#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003318static void
Fred Drake509d79a2000-07-08 04:04:38 +00003319MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003320{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003321 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003322}
Guido van Rossumad4db171998-06-13 13:56:28 +00003323#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003324
Guido van Rossum00d93061998-05-28 23:06:38 +00003325static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003326
Guido van Rossum18468821994-06-20 07:49:28 +00003327static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003328EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003329{
Guido van Rossumad4db171998-06-13 13:56:28 +00003330#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003331 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003332#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003333 PyEval_RestoreThread(event_tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003334 stdin_ready = 0;
3335 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003336#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003337 tfile = fileno(stdin);
3338 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003339#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003340 while (!errorInCmd && !stdin_ready) {
3341 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003342#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003343 if (_kbhit()) {
3344 stdin_ready = 1;
3345 break;
3346 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003347#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003348 Py_BEGIN_ALLOW_THREADS
3349 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3350 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003352 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003353
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003354 tcl_tstate = NULL;
3355 if(tcl_lock)PyThread_release_lock(tcl_lock);
3356 if (result == 0)
3357 Sleep(Tkinter_busywaitinterval);
3358 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003359
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003360 if (result < 0)
3361 break;
3362 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003363#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003364 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003365#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003366 if (errorInCmd) {
3367 errorInCmd = 0;
3368 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3369 excInCmd = valInCmd = trbInCmd = NULL;
3370 PyErr_Print();
3371 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003372 PyEval_SaveThread();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003373 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003374}
Guido van Rossum18468821994-06-20 07:49:28 +00003375
Guido van Rossum00d93061998-05-28 23:06:38 +00003376#endif
3377
Guido van Rossum7bf15641998-05-22 18:28:17 +00003378static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003379EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003380{
Guido van Rossum00d93061998-05-28 23:06:38 +00003381#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003382 if (PyOS_InputHook == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003383 event_tstate = PyThreadState_Get();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003384 PyOS_InputHook = EventHook;
3385 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003386#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003387}
3388
3389static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003390DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003391{
Guido van Rossum00d93061998-05-28 23:06:38 +00003392#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003393 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3394 PyOS_InputHook = NULL;
3395 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003396#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003397}
3398
Barry Warsawfa701a81997-01-16 00:15:11 +00003399
Martin v. Löwis1a214512008-06-11 05:26:20 +00003400static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003401 PyModuleDef_HEAD_INIT,
3402 "_tkinter",
3403 NULL,
3404 -1,
3405 moduleMethods,
3406 NULL,
3407 NULL,
3408 NULL,
3409 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003410};
3411
Mark Hammond62b1ab12002-07-23 06:31:15 +00003412PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003413PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003414{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003415 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003416
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003417 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003418 if (tcl_lock == NULL)
3419 return NULL;
Guido van Rossumae92f011996-08-21 19:03:36 +00003420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003421 m = PyModule_Create(&_tkintermodule);
3422 if (m == NULL)
3423 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003424
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003425 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3426 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003427 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003428 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003429 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003430 Py_INCREF(o);
3431 if (PyModule_AddObject(m, "TclError", o)) {
3432 Py_DECREF(o);
3433 Py_DECREF(m);
3434 return NULL;
3435 }
3436 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003437
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003438 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3439 Py_DECREF(m);
3440 return NULL;
3441 }
3442 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3443 Py_DECREF(m);
3444 return NULL;
3445 }
3446 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3447 Py_DECREF(m);
3448 return NULL;
3449 }
3450 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3451 Py_DECREF(m);
3452 return NULL;
3453 }
3454 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3455 Py_DECREF(m);
3456 return NULL;
3457 }
3458 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3459 Py_DECREF(m);
3460 return NULL;
3461 }
3462 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3463 Py_DECREF(m);
3464 return NULL;
3465 }
3466 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3467 Py_DECREF(m);
3468 return NULL;
3469 }
3470 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3471 Py_DECREF(m);
3472 return NULL;
3473 }
3474 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3475 Py_DECREF(m);
3476 return NULL;
3477 }
3478 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3479 Py_DECREF(m);
3480 return NULL;
3481 }
3482
3483 o = PyType_FromSpec(&Tkapp_Type_spec);
3484 if (o == NULL) {
3485 Py_DECREF(m);
3486 return NULL;
3487 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003488 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003489 if (PyModule_AddObject(m, "TkappType", o)) {
3490 Py_DECREF(o);
3491 Py_DECREF(m);
3492 return NULL;
3493 }
3494 Tkapp_Type = o;
3495
3496 o = PyType_FromSpec(&Tktt_Type_spec);
3497 if (o == NULL) {
3498 Py_DECREF(m);
3499 return NULL;
3500 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003501 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003502 if (PyModule_AddObject(m, "TkttType", o)) {
3503 Py_DECREF(o);
3504 Py_DECREF(m);
3505 return NULL;
3506 }
3507 Tktt_Type = o;
3508
3509 o = PyType_FromSpec(&PyTclObject_Type_spec);
3510 if (o == NULL) {
3511 Py_DECREF(m);
3512 return NULL;
3513 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003514 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003515 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3516 Py_DECREF(o);
3517 Py_DECREF(m);
3518 return NULL;
3519 }
3520 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003521
3522#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003523 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3524 * start waking up. Note that Tcl_FindExecutable will do this, this
3525 * code must be above it! The original warning from
3526 * tkMacOSXAppInit.c is copied below.
3527 *
3528 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3529 * Tcl interpreter for now. It probably should work to do this
3530 * in the other order, but for now it doesn't seem to.
3531 *
3532 */
3533 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003534#endif
3535
3536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003537 /* This helps the dynamic loader; in Unicode aware Tcl versions
3538 it also helps Tcl find its encodings. */
3539 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3540 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003541 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003542 if (cexe) {
3543#ifdef MS_WINDOWS
3544 int set_var = 0;
3545 PyObject *str_path;
3546 wchar_t *wcs_path;
3547 DWORD ret;
3548
3549 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3550
3551 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3552 str_path = _get_tcl_lib_path();
3553 if (str_path == NULL && PyErr_Occurred()) {
Brandt Bucher289cf0f2019-11-18 06:52:36 -08003554 Py_DECREF(m);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003555 return NULL;
3556 }
3557 if (str_path != NULL) {
3558 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3559 if (wcs_path == NULL) {
Brandt Bucher289cf0f2019-11-18 06:52:36 -08003560 Py_DECREF(m);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003561 return NULL;
3562 }
3563 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3564 set_var = 1;
3565 }
3566 }
3567
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003568 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003569
3570 if (set_var) {
3571 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3572 PyMem_Free(wcs_path);
3573 }
3574#else
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003575 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003576#endif /* MS_WINDOWS */
3577 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003578 Py_XDECREF(cexe);
3579 Py_DECREF(uexe);
3580 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003581
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003582 if (PyErr_Occurred()) {
3583 Py_DECREF(m);
3584 return NULL;
3585 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003586
Guido van Rossum43ff8681998-07-14 18:02:13 +00003587#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003588 /* This was not a good idea; through <Destroy> bindings,
3589 Tcl_Finalize() may invoke Python code but at that point the
3590 interpreter and thread state have already been destroyed! */
3591 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003592#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003593 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003594}