blob: b30141d4497bda320b3f0d89d8092362ef6abf59 [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();
Serhiy Storchakaa26215d2020-11-15 18:16:59 +0200398 /* Tcl encodes null character as \xc0\x80.
399 https://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8 */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300400 if (memchr(s, '\xc0', size)) {
401 char *q;
402 const char *e = s + size;
403 q = buf = (char *)PyMem_Malloc(size);
404 if (buf == NULL) {
405 PyErr_NoMemory();
406 return NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200407 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300408 while (s != e) {
409 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
410 *q++ = '\0';
411 s += 2;
412 }
413 else
414 *q++ = *s++;
415 }
416 s = buf;
417 size = q - s;
418 }
419 r = PyUnicode_DecodeUTF8(s, size, "surrogateescape");
420 if (buf != NULL) {
421 PyMem_Free(buf);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200422 }
Serhiy Storchakaa26215d2020-11-15 18:16:59 +0200423 if (r == NULL || PyUnicode_KIND(r) == PyUnicode_1BYTE_KIND) {
424 return r;
425 }
426
427 /* In CESU-8 non-BMP characters are represented as a surrogate pair,
428 like in UTF-16, and then each surrogate code point is encoded in UTF-8.
429 https://en.wikipedia.org/wiki/CESU-8 */
430 Py_ssize_t len = PyUnicode_GET_LENGTH(r);
431 Py_ssize_t i, j;
432 /* All encoded surrogate characters start with \xED. */
433 i = PyUnicode_FindChar(r, 0xdcED, 0, len, 1);
434 if (i == -2) {
435 Py_DECREF(r);
436 return NULL;
437 }
438 if (i == -1) {
439 return r;
440 }
441 Py_UCS4 *u = PyUnicode_AsUCS4Copy(r);
442 Py_DECREF(r);
443 if (u == NULL) {
444 return NULL;
445 }
446 Py_UCS4 ch;
447 for (j = i; i < len; i++, u[j++] = ch) {
448 Py_UCS4 ch1, ch2, ch3, high, low;
449 /* Low surrogates U+D800 - U+DBFF are encoded as
450 \xED\xA0\x80 - \xED\xAF\xBF. */
451 ch1 = ch = u[i];
452 if (ch1 != 0xdcED) continue;
453 ch2 = u[i + 1];
454 if (!(0xdcA0 <= ch2 && ch2 <= 0xdcAF)) continue;
455 ch3 = u[i + 2];
456 if (!(0xdc80 <= ch3 && ch3 <= 0xdcBF)) continue;
457 high = 0xD000 | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F);
458 assert(Py_UNICODE_IS_HIGH_SURROGATE(high));
459 /* High surrogates U+DC00 - U+DFFF are encoded as
460 \xED\xB0\x80 - \xED\xBF\xBF. */
461 ch1 = u[i + 3];
462 if (ch1 != 0xdcED) continue;
463 ch2 = u[i + 4];
464 if (!(0xdcB0 <= ch2 && ch2 <= 0xdcBF)) continue;
465 ch3 = u[i + 5];
466 if (!(0xdc80 <= ch3 && ch3 <= 0xdcBF)) continue;
467 low = 0xD000 | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F);
468 assert(Py_UNICODE_IS_HIGH_SURROGATE(high));
469 ch = Py_UNICODE_JOIN_SURROGATES(high, low);
470 i += 5;
471 }
472 r = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, u, j);
473 PyMem_Free(u);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200474 return r;
475}
476
477static PyObject *
478unicodeFromTclString(const char *s)
479{
480 return unicodeFromTclStringAndSize(s, strlen(s));
481}
482
483static PyObject *
484unicodeFromTclObj(Tcl_Obj *value)
485{
486 int len;
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300487#if USE_TCL_UNICODE
488 int byteorder = NATIVE_BYTEORDER;
489 const Tcl_UniChar *u = Tcl_GetUnicodeFromObj(value, &len);
490 if (sizeof(Tcl_UniChar) == 2)
491 return PyUnicode_DecodeUTF16((const char *)u, len * 2,
492 "surrogatepass", &byteorder);
493 else if (sizeof(Tcl_UniChar) == 4)
494 return PyUnicode_DecodeUTF32((const char *)u, len * 4,
495 "surrogatepass", &byteorder);
496 else
497 Py_UNREACHABLE();
498#else
499 const char *s = Tcl_GetStringFromObj(value, &len);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200500 return unicodeFromTclStringAndSize(s, len);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300501#endif
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200502}
503
504
505static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300506Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000507{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000508 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300509 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000512 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300513 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000514 }
Guido van Rossum18468821994-06-20 07:49:28 +0000515
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000516 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
517 /* Not a list.
518 * Could be a quoted string containing funnies, e.g. {"}.
519 * Return the string itself.
520 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200521 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000522 }
Guido van Rossum18468821994-06-20 07:49:28 +0000523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 if (argc == 0)
525 v = PyUnicode_FromString("");
526 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200527 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000528 else if ((v = PyTuple_New(argc)) != NULL) {
529 int i;
530 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000531
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000532 for (i = 0; i < argc; i++) {
533 if ((w = Split(argv[i])) == NULL) {
534 Py_DECREF(v);
535 v = NULL;
536 break;
537 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300538 PyTuple_SET_ITEM(v, i, w);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000539 }
540 }
541 Tcl_Free(FREECAST argv);
542 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000543}
544
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300545/* In some cases, Tcl will still return strings that are supposed to
546 be lists. SplitObj walks through a nested tuple, finding string
547 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000548
Martin v. Löwis59683e82008-06-13 07:50:45 +0000549static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000550SplitObj(PyObject *arg)
551{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000552 if (PyTuple_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200553 Py_ssize_t i, size;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000555
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300556 size = PyTuple_GET_SIZE(arg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 result = NULL;
558 /* Recursively invoke SplitObj for all tuple items.
559 If this does not return a new object, no action is
560 needed. */
561 for(i = 0; i < size; i++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300562 elem = PyTuple_GET_ITEM(arg, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000563 newelem = SplitObj(elem);
564 if (!newelem) {
565 Py_XDECREF(result);
566 return NULL;
567 }
568 if (!result) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200569 Py_ssize_t k;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000570 if (newelem == elem) {
571 Py_DECREF(newelem);
572 continue;
573 }
574 result = PyTuple_New(size);
575 if (!result)
576 return NULL;
577 for(k = 0; k < i; k++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300578 elem = PyTuple_GET_ITEM(arg, k);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000579 Py_INCREF(elem);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300580 PyTuple_SET_ITEM(result, k, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000581 }
582 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300583 PyTuple_SET_ITEM(result, i, newelem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000584 }
585 if (result)
586 return result;
587 /* Fall through, returning arg. */
588 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300589 else if (PyList_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200590 Py_ssize_t i, size;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300591 PyObject *elem, *newelem, *result;
592
593 size = PyList_GET_SIZE(arg);
594 result = PyTuple_New(size);
595 if (!result)
596 return NULL;
597 /* Recursively invoke SplitObj for all list items. */
598 for(i = 0; i < size; i++) {
599 elem = PyList_GET_ITEM(arg, i);
600 newelem = SplitObj(elem);
601 if (!newelem) {
602 Py_XDECREF(result);
603 return NULL;
604 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300605 PyTuple_SET_ITEM(result, i, newelem);
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300606 }
607 return result;
608 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300609 else if (PyUnicode_Check(arg)) {
610 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300611 const char **argv;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200612 const char *list = PyUnicode_AsUTF8(arg);
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300613
614 if (list == NULL ||
615 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
616 Py_INCREF(arg);
617 return arg;
618 }
619 Tcl_Free(FREECAST argv);
620 if (argc > 1)
621 return Split(list);
622 /* Fall through, returning arg. */
623 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000624 else if (PyBytes_Check(arg)) {
625 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300626 const char **argv;
Serhiy Storchaka8f87eef2020-04-12 14:58:27 +0300627 const char *list = PyBytes_AS_STRING(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000628
Serhiy Storchaka8f87eef2020-04-12 14:58:27 +0300629 if (Tcl_SplitList((Tcl_Interp *)NULL, (char *)list, &argc, &argv) != TCL_OK) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 Py_INCREF(arg);
631 return arg;
632 }
633 Tcl_Free(FREECAST argv);
634 if (argc > 1)
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300635 return Split(PyBytes_AS_STRING(arg));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 /* Fall through, returning arg. */
637 }
638 Py_INCREF(arg);
639 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000640}
Barry Warsawfa701a81997-01-16 00:15:11 +0000641
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000642
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +0300643/*[clinic input]
644module _tkinter
645class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec"
646class _tkinter.Tcl_Obj "PyTclObject *" "&PyTclObject_Type_spec"
647class _tkinter.tktimertoken "TkttObject *" "&Tktt_Type_spec"
648[clinic start generated code]*/
649/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b1ebf15c162ee229]*/
650
Guido van Rossum18468821994-06-20 07:49:28 +0000651/**** Tkapp Object ****/
652
653#ifndef WITH_APPINIT
654int
Fred Drake509d79a2000-07-08 04:04:38 +0000655Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000656{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000657 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000659 if (Tcl_Init(interp) == TCL_ERROR) {
660 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
661 return TCL_ERROR;
662 }
Guilherme Polob681df42009-02-09 22:33:59 +0000663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 _tkinter_skip_tk_init = Tcl_GetVar(interp,
665 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
666 if (_tkinter_skip_tk_init != NULL &&
667 strcmp(_tkinter_skip_tk_init, "1") == 0) {
668 return TCL_OK;
669 }
Guilherme Polob681df42009-02-09 22:33:59 +0000670
671#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000672 if (tk_load_failed) {
673 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
674 return TCL_ERROR;
675 }
Guilherme Polob681df42009-02-09 22:33:59 +0000676#endif
677
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000678 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000679#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000680 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000681#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
683 return TCL_ERROR;
684 }
Guilherme Polob681df42009-02-09 22:33:59 +0000685
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000686 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000687}
688#endif /* !WITH_APPINIT */
689
Guido van Rossum18468821994-06-20 07:49:28 +0000690
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691
Barry Warsawfa701a81997-01-16 00:15:11 +0000692
693/* Initialize the Tk application; see the `main' function in
694 * `tkMain.c'.
695 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000696
Thomas Wouters58d05102000-07-24 14:43:35 +0000697static void EnableEventHook(void); /* Forward */
698static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000699
Barry Warsawfa701a81997-01-16 00:15:11 +0000700static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300701Tkapp_New(const char *screenName, const char *className,
702 int interactive, int wantobjects, int wantTk, int sync,
703 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000704{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000705 TkappObject *v;
706 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000707
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300708 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000709 if (v == NULL)
710 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000711
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000712 v->interp = Tcl_CreateInterp();
713 v->wantobjects = wantobjects;
714 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
715 TCL_GLOBAL_ONLY) != NULL;
716 v->thread_id = Tcl_GetCurrentThread();
717 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000718
719#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300721 PyErr_SetString(PyExc_RuntimeError,
722 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000723 Py_DECREF(v);
724 return 0;
725 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000726#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000727 if (v->threaded && tcl_lock) {
728 /* If Tcl is threaded, we don't need the lock. */
729 PyThread_free_lock(tcl_lock);
730 tcl_lock = NULL;
731 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000732
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200733 v->OldBooleanType = Tcl_GetObjType("boolean");
734 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000735 v->ByteArrayType = Tcl_GetObjType("bytearray");
736 v->DoubleType = Tcl_GetObjType("double");
737 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300738 v->WideIntType = Tcl_GetObjType("wideInt");
739 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000740 v->ListType = Tcl_GetObjType("list");
741 v->ProcBodyType = Tcl_GetObjType("procbody");
742 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000743
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000744 /* Delete the 'exit' command, which can screw things up */
745 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000746
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000747 if (screenName != NULL)
748 Tcl_SetVar2(v->interp, "env", "DISPLAY",
749 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000750
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000751 if (interactive)
752 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
753 else
754 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000755
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000756 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200757 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000758 if (!argv0) {
759 PyErr_NoMemory();
760 Py_DECREF(v);
761 return NULL;
762 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000763
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000764 strcpy(argv0, className);
Jordon Xu2ec70102019-09-11 00:04:08 +0800765 if (Py_ISUPPER(argv0[0]))
766 argv0[0] = Py_TOLOWER(argv0[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000767 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200768 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000769
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000770 if (! wantTk) {
771 Tcl_SetVar(v->interp,
772 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
773 }
Guilherme Polob681df42009-02-09 22:33:59 +0000774#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 else if (tk_load_failed) {
776 Tcl_SetVar(v->interp,
777 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
778 }
Guilherme Polob681df42009-02-09 22:33:59 +0000779#endif
David Aschere2b4b322004-02-18 05:59:53 +0000780
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000781 /* some initial arguments need to be in argv */
782 if (sync || use) {
783 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200784 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000786 if (sync)
787 len += sizeof "-sync";
788 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200789 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000790
Victor Stinneree6c3c72014-09-11 17:50:21 +0200791 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000792 if (!args) {
793 PyErr_NoMemory();
794 Py_DECREF(v);
795 return NULL;
796 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000798 args[0] = '\0';
799 if (sync)
800 strcat(args, "-sync");
801 if (use) {
802 if (sync)
803 strcat(args, " ");
804 strcat(args, "-use ");
805 strcat(args, use);
806 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000807
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000808 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200809 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000810 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000811
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500812#ifdef MS_WINDOWS
813 {
814 PyObject *str_path;
815 PyObject *utf8_path;
816 DWORD ret;
817
818 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
819 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
820 str_path = _get_tcl_lib_path();
821 if (str_path == NULL && PyErr_Occurred()) {
822 return NULL;
823 }
824 if (str_path != NULL) {
825 utf8_path = PyUnicode_AsUTF8String(str_path);
826 if (utf8_path == NULL) {
827 return NULL;
828 }
829 Tcl_SetVar(v->interp,
830 "tcl_library",
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300831 PyBytes_AS_STRING(utf8_path),
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500832 TCL_GLOBAL_ONLY);
833 Py_DECREF(utf8_path);
834 }
835 }
836 }
837#endif
838
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000839 if (Tcl_AppInit(v->interp) != TCL_OK) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300840 PyObject *result = Tkinter_Error(v);
Guilherme Polob681df42009-02-09 22:33:59 +0000841#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000842 if (wantTk) {
843 const char *_tkinter_tk_failed;
844 _tkinter_tk_failed = Tcl_GetVar(v->interp,
845 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000846
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000847 if ( _tkinter_tk_failed != NULL &&
848 strcmp(_tkinter_tk_failed, "1") == 0) {
849 tk_load_failed = 1;
850 }
851 }
Guilherme Polob681df42009-02-09 22:33:59 +0000852#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000853 Py_DECREF((PyObject *)v);
854 return (TkappObject *)result;
855 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000856
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000857 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000858
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000859 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000860}
861
Barry Warsawfa701a81997-01-16 00:15:11 +0000862
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000863static void
864Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000865 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000866{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000867 Py_BEGIN_ALLOW_THREADS;
868 Tcl_MutexLock(mutex);
869 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
870 Tcl_ThreadAlert(self->thread_id);
871 Tcl_ConditionWait(cond, mutex, NULL);
872 Tcl_MutexUnlock(mutex);
873 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000874}
875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000876
Guido van Rossum18468821994-06-20 07:49:28 +0000877/** Tcl Eval **/
878
Martin v. Löwisffad6332002-11-26 09:28:05 +0000879typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000880 PyObject_HEAD
881 Tcl_Obj *value;
882 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000883} PyTclObject;
884
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300885static PyObject *PyTclObject_Type;
Dong-hee Na1b55b652020-02-17 19:09:15 +0900886#define PyTclObject_Check(v) Py_IS_TYPE(v, (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000887
888static PyObject *
889newPyTclObject(Tcl_Obj *arg)
890{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000891 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300892 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000893 if (self == NULL)
894 return NULL;
895 Tcl_IncrRefCount(arg);
896 self->value = arg;
897 self->string = NULL;
898 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000899}
900
901static void
902PyTclObject_dealloc(PyTclObject *self)
903{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200904 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000905 Tcl_DecrRefCount(self->value);
906 Py_XDECREF(self->string);
907 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200908 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000909}
910
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000911/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000912PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000913"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000914
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000915static PyObject *
916PyTclObject_string(PyTclObject *self, void *ignored)
917{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000918 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200919 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000920 if (!self->string)
921 return NULL;
922 }
923 Py_INCREF(self->string);
924 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000925}
926
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000927static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200928PyTclObject_str(PyTclObject *self)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000929{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200930 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000931 Py_INCREF(self->string);
932 return self->string;
933 }
934 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200935 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000936}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000937
Martin v. Löwisffad6332002-11-26 09:28:05 +0000938static PyObject *
939PyTclObject_repr(PyTclObject *self)
940{
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200941 PyObject *repr, *str = PyTclObject_str(self);
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300942 if (str == NULL)
943 return NULL;
944 repr = PyUnicode_FromFormat("<%s object: %R>",
945 self->value->typePtr->name, str);
946 Py_DECREF(str);
947 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000948}
949
Mark Dickinson211c6252009-02-01 10:28:51 +0000950static PyObject *
951PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000952{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000953 int result;
Mark Dickinson211c6252009-02-01 10:28:51 +0000954
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000955 /* neither argument should be NULL, unless something's gone wrong */
956 if (self == NULL || other == NULL) {
957 PyErr_BadInternalCall();
958 return NULL;
959 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000960
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000961 /* both arguments should be instances of PyTclObject */
962 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
stratakise8b19652017-11-02 11:32:54 +0100963 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000964 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000965
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000966 if (self == other)
967 /* fast path when self and other are identical */
968 result = 0;
969 else
970 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
971 Tcl_GetString(((PyTclObject *)other)->value));
stratakise8b19652017-11-02 11:32:54 +0100972 Py_RETURN_RICHCOMPARE(result, 0, op);
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000973}
974
Martin v. Löwis39195712003-01-04 00:33:13 +0000975PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
976
Martin v. Löwisffad6332002-11-26 09:28:05 +0000977static PyObject*
978get_typename(PyTclObject* obj, void* ignored)
979{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200980 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000981}
982
Martin v. Löwis39195712003-01-04 00:33:13 +0000983
Martin v. Löwisffad6332002-11-26 09:28:05 +0000984static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000985 {"typename", (getter)get_typename, NULL, get_typename__doc__},
986 {"string", (getter)PyTclObject_string, NULL,
987 PyTclObject_string__doc__},
988 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000989};
990
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300991static PyType_Slot PyTclObject_Type_slots[] = {
992 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
993 {Py_tp_repr, (reprfunc)PyTclObject_repr},
994 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200995 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300996 {Py_tp_richcompare, PyTclObject_richcompare},
997 {Py_tp_getset, PyTclObject_getsetlist},
998 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000999};
1000
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03001001static PyType_Spec PyTclObject_Type_spec = {
1002 "_tkinter.Tcl_Obj",
1003 sizeof(PyTclObject),
1004 0,
1005 Py_TPFLAGS_DEFAULT,
1006 PyTclObject_Type_slots,
1007};
1008
1009
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -07001010#if SIZE_MAX > INT_MAX
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001011#define CHECK_STRING_LENGTH(s) do { \
1012 if (s != NULL && strlen(s) >= INT_MAX) { \
1013 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
1014 return NULL; \
1015 } } while(0)
1016#else
1017#define CHECK_STRING_LENGTH(s)
1018#endif
1019
Andrew York003708b2020-05-15 03:43:58 -07001020#ifdef HAVE_LIBTOMMATH
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001021static Tcl_Obj*
1022asBignumObj(PyObject *value)
1023{
1024 Tcl_Obj *result;
1025 int neg;
1026 PyObject *hexstr;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +02001027 const char *hexchars;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001028 mp_int bigValue;
1029
1030 neg = Py_SIZE(value) < 0;
1031 hexstr = _PyLong_Format(value, 16);
1032 if (hexstr == NULL)
1033 return NULL;
1034 hexchars = PyUnicode_AsUTF8(hexstr);
1035 if (hexchars == NULL) {
1036 Py_DECREF(hexstr);
1037 return NULL;
1038 }
1039 hexchars += neg + 2; /* skip sign and "0x" */
1040 mp_init(&bigValue);
1041 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
1042 mp_clear(&bigValue);
1043 Py_DECREF(hexstr);
1044 PyErr_NoMemory();
1045 return NULL;
1046 }
1047 Py_DECREF(hexstr);
1048 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
1049 result = Tcl_NewBignumObj(&bigValue);
1050 mp_clear(&bigValue);
1051 if (result == NULL) {
1052 PyErr_NoMemory();
1053 return NULL;
1054 }
1055 return result;
1056}
1057#endif
1058
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001059static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001060AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001061{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001062 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001063
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001064 if (PyBytes_Check(value)) {
1065 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
1066 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1067 return NULL;
1068 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +03001069 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001070 (int)PyBytes_GET_SIZE(value));
1071 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001072
1073 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001074 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001075
1076 if (PyLong_CheckExact(value)) {
1077 int overflow;
1078 long longValue;
1079#ifdef TCL_WIDE_INT_TYPE
1080 Tcl_WideInt wideValue;
1081#endif
1082 longValue = PyLong_AsLongAndOverflow(value, &overflow);
1083 if (!overflow) {
1084 return Tcl_NewLongObj(longValue);
1085 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001086 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001087 fall through to wideInt handling. */
1088#ifdef TCL_WIDE_INT_TYPE
1089 if (_PyLong_AsByteArray((PyLongObject *)value,
1090 (unsigned char *)(void *)&wideValue,
1091 sizeof(wideValue),
1092 PY_LITTLE_ENDIAN,
1093 /* signed */ 1) == 0) {
1094 return Tcl_NewWideIntObj(wideValue);
1095 }
1096 PyErr_Clear();
1097#endif
1098 /* If there is an overflow in the wideInt conversion,
1099 fall through to bignum handling. */
Andrew York003708b2020-05-15 03:43:58 -07001100#ifdef HAVE_LIBTOMMATH
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001101 return asBignumObj(value);
1102#endif
1103 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001104 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001106
1107 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001108 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001109
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +03001110 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001111 Tcl_Obj **argv;
1112 Py_ssize_t size, i;
1113
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001114 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001115 if (size == 0)
1116 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001117 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001118 PyErr_SetString(PyExc_OverflowError,
1119 PyTuple_Check(value) ? "tuple is too long" :
1120 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001121 return NULL;
1122 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001123 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
1124 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001125 PyErr_NoMemory();
1126 return NULL;
1127 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001128 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001129 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001130 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001131 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001132 return result;
1133 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001134
1135 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001136 if (PyUnicode_READY(value) == -1)
1137 return NULL;
1138
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001139 Py_ssize_t size = PyUnicode_GET_LENGTH(value);
1140 if (size == 0) {
1141 return Tcl_NewStringObj("", 0);
1142 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001143 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1144 PyErr_SetString(PyExc_OverflowError, "string is too long");
1145 return NULL;
1146 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001147 if (PyUnicode_IS_ASCII(value)) {
1148 return Tcl_NewStringObj((const char *)PyUnicode_DATA(value),
1149 (int)size);
1150 }
1151
1152 PyObject *encoded;
1153#if USE_TCL_UNICODE
1154 if (sizeof(Tcl_UniChar) == 2)
1155 encoded = _PyUnicode_EncodeUTF16(value,
1156 "surrogatepass", NATIVE_BYTEORDER);
1157 else if (sizeof(Tcl_UniChar) == 4)
1158 encoded = _PyUnicode_EncodeUTF32(value,
1159 "surrogatepass", NATIVE_BYTEORDER);
1160 else
1161 Py_UNREACHABLE();
1162#else
1163 encoded = _PyUnicode_AsUTF8String(value, "surrogateescape");
1164#endif
1165 if (!encoded) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001166 return NULL;
1167 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001168 size = PyBytes_GET_SIZE(encoded);
1169 if (size > INT_MAX) {
1170 Py_DECREF(encoded);
1171 PyErr_SetString(PyExc_OverflowError, "string is too long");
1172 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001173 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001174#if USE_TCL_UNICODE
1175 result = Tcl_NewUnicodeObj((const Tcl_UniChar *)PyBytes_AS_STRING(encoded),
1176 (int)(size / sizeof(Tcl_UniChar)));
1177#else
1178 result = Tcl_NewStringObj(PyBytes_AS_STRING(encoded), (int)size);
1179#endif
1180 Py_DECREF(encoded);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001181 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001182 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001183
1184 if (PyTclObject_Check(value)) {
Serhiy Storchakadf13df42018-10-23 22:40:54 +03001185 return ((PyTclObject*)value)->value;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001186 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001187
1188 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001189 PyObject *v = PyObject_Str(value);
1190 if (!v)
1191 return 0;
1192 result = AsObj(v);
1193 Py_DECREF(v);
1194 return result;
1195 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001196}
1197
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001198static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001199fromBoolean(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001200{
1201 int boolValue;
1202 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1203 return Tkinter_Error(tkapp);
1204 return PyBool_FromLong(boolValue);
1205}
1206
Martin v. Löwisffad6332002-11-26 09:28:05 +00001207static PyObject*
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001208fromWideIntObj(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001209{
1210 Tcl_WideInt wideValue;
1211 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001212 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1213 return PyLong_FromLongLong(wideValue);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001214 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1215 sizeof(wideValue),
1216 PY_LITTLE_ENDIAN,
1217 /* signed */ 1);
1218 }
1219 return NULL;
1220}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001221
Andrew York003708b2020-05-15 03:43:58 -07001222#ifdef HAVE_LIBTOMMATH
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001223static PyObject*
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001224fromBignumObj(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001225{
1226 mp_int bigValue;
1227 unsigned long numBytes;
1228 unsigned char *bytes;
1229 PyObject *res;
1230
1231 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1232 return Tkinter_Error(tkapp);
1233 numBytes = mp_unsigned_bin_size(&bigValue);
1234 bytes = PyMem_Malloc(numBytes);
1235 if (bytes == NULL) {
1236 mp_clear(&bigValue);
1237 return PyErr_NoMemory();
1238 }
1239 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1240 &numBytes) != MP_OKAY) {
1241 mp_clear(&bigValue);
1242 PyMem_Free(bytes);
1243 return PyErr_NoMemory();
1244 }
1245 res = _PyLong_FromByteArray(bytes, numBytes,
1246 /* big-endian */ 0,
1247 /* unsigned */ 0);
1248 PyMem_Free(bytes);
1249 if (res != NULL && bigValue.sign == MP_NEG) {
1250 PyObject *res2 = PyNumber_Negative(res);
1251 Py_DECREF(res);
1252 res = res2;
1253 }
1254 mp_clear(&bigValue);
1255 return res;
1256}
1257#endif
1258
Martin v. Löwisffad6332002-11-26 09:28:05 +00001259static PyObject*
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001260FromObj(TkappObject *tkapp, Tcl_Obj *value)
Martin v. Löwisffad6332002-11-26 09:28:05 +00001261{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001262 PyObject *result = NULL;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001263 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001264
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001265 if (value->typePtr == NULL) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001266 return unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001267 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001268
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001269 if (value->typePtr == tkapp->BooleanType ||
1270 value->typePtr == tkapp->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001271 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001272 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001273
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001274 if (value->typePtr == tkapp->ByteArrayType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001275 int size;
1276 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1277 return PyBytes_FromStringAndSize(data, size);
1278 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001279
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001280 if (value->typePtr == tkapp->DoubleType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001281 return PyFloat_FromDouble(value->internalRep.doubleValue);
1282 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001283
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001284 if (value->typePtr == tkapp->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001285 long longValue;
1286 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1287 return PyLong_FromLong(longValue);
1288 /* If there is an error in the long conversion,
1289 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001290 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001291
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001292 if (value->typePtr == tkapp->IntType ||
1293 value->typePtr == tkapp->WideIntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001294 result = fromWideIntObj(tkapp, value);
1295 if (result != NULL || PyErr_Occurred())
1296 return result;
1297 Tcl_ResetResult(interp);
1298 /* If there is an error in the wideInt conversion,
1299 fall through to bignum handling. */
1300 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001301
Andrew York003708b2020-05-15 03:43:58 -07001302#ifdef HAVE_LIBTOMMATH
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001303 if (value->typePtr == tkapp->IntType ||
1304 value->typePtr == tkapp->WideIntType ||
1305 value->typePtr == tkapp->BignumType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001306 return fromBignumObj(tkapp, value);
1307 }
1308#endif
1309
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001310 if (value->typePtr == tkapp->ListType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001311 int size;
1312 int i, status;
1313 PyObject *elem;
1314 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001315
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001316 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001317 if (status == TCL_ERROR)
1318 return Tkinter_Error(tkapp);
1319 result = PyTuple_New(size);
1320 if (!result)
1321 return NULL;
1322 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001323 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001324 if (status == TCL_ERROR) {
1325 Py_DECREF(result);
1326 return Tkinter_Error(tkapp);
1327 }
1328 elem = FromObj(tkapp, tcl_elem);
1329 if (!elem) {
1330 Py_DECREF(result);
1331 return NULL;
1332 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001333 PyTuple_SET_ITEM(result, i, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001334 }
1335 return result;
1336 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001337
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001338 if (value->typePtr == tkapp->ProcBodyType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001339 /* fall through: return tcl object. */
1340 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001341
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001342 if (value->typePtr == tkapp->StringType) {
1343 return unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001344 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001345
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001346#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001347 if (tkapp->BooleanType == NULL &&
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001348 strcmp(value->typePtr->name, "booleanString") == 0) {
1349 /* booleanString type is not registered in Tcl */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001350 tkapp->BooleanType = value->typePtr;
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001351 return fromBoolean(tkapp, value);
1352 }
1353#endif
1354
Andrew York003708b2020-05-15 03:43:58 -07001355#ifdef HAVE_LIBTOMMATH
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001356 if (tkapp->BignumType == NULL &&
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001357 strcmp(value->typePtr->name, "bignum") == 0) {
1358 /* bignum type is not registered in Tcl */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001359 tkapp->BignumType = value->typePtr;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001360 return fromBignumObj(tkapp, value);
1361 }
1362#endif
1363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001364 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001365}
1366
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001367/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001368TCL_DECLARE_MUTEX(call_mutex)
1369
1370typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001371 Tcl_Event ev; /* Must be first */
1372 TkappObject *self;
1373 PyObject *args;
1374 int flags;
1375 PyObject **res;
1376 PyObject **exc_type, **exc_value, **exc_tb;
1377 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001378} Tkapp_CallEvent;
1379
1380void
1381Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001382{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001383 int i;
1384 for (i = 0; i < objc; i++)
1385 Tcl_DecrRefCount(objv[i]);
1386 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001387 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001388}
Guido van Rossum18468821994-06-20 07:49:28 +00001389
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001390/* Convert Python objects to Tcl objects. This must happen in the
1391 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001392
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001393static Tcl_Obj**
1394Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1395{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001396 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001397 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001398 if (args == NULL)
1399 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001400
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001401 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001402 objv[0] = AsObj(args);
Serhiy Storchaka0b3ec192017-03-23 17:53:47 +02001403 if (objv[0] == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001404 goto finally;
1405 objc = 1;
1406 Tcl_IncrRefCount(objv[0]);
1407 }
1408 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001409 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001411 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001412 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001413 PyErr_SetString(PyExc_OverflowError,
1414 PyTuple_Check(args) ? "tuple is too long" :
1415 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001416 return NULL;
1417 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001418 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001419 if (objv == NULL) {
1420 PyErr_NoMemory();
1421 objc = 0;
1422 goto finally;
1423 }
1424 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001426 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001427 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001428 if (v == Py_None) {
1429 objc = i;
1430 break;
1431 }
1432 objv[i] = AsObj(v);
1433 if (!objv[i]) {
1434 /* Reset objc, so it attempts to clear
1435 objects only up to i. */
1436 objc = i;
1437 goto finally;
1438 }
1439 Tcl_IncrRefCount(objv[i]);
1440 }
1441 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001442 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001443 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001444finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001445 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001446 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001447}
Guido van Rossum212643f1998-04-29 16:22:14 +00001448
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001449/* Convert the results of a command call into a Python string. */
1450
1451static PyObject *
1452Tkapp_UnicodeResult(TkappObject *self)
1453{
1454 return unicodeFromTclObj(Tcl_GetObjResult(self->interp));
1455}
1456
1457
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001458/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001459
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001460static PyObject *
1461Tkapp_ObjectResult(TkappObject *self)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001462{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001463 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001464 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001465 if (self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001466 /* Not sure whether the IncrRef is necessary, but something
1467 may overwrite the interpreter result while we are
1468 converting it. */
1469 Tcl_IncrRefCount(value);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001470 res = FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001471 Tcl_DecrRefCount(value);
1472 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001473 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001474 }
1475 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001476}
Guido van Rossum632de272000-03-29 00:19:50 +00001477
Benjamin Peterson5879d412009-03-30 14:51:56 +00001478
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001479/* Tkapp_CallProc is the event procedure that is executed in the context of
1480 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1481 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001482
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001483static int
1484Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1485{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001486 Tcl_Obj *objStore[ARGSZ];
1487 Tcl_Obj **objv;
1488 int objc;
1489 int i;
1490 ENTER_PYTHON
1491 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1492 if (!objv) {
1493 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1494 *(e->res) = NULL;
1495 }
1496 LEAVE_PYTHON
1497 if (!objv)
1498 goto done;
1499 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1500 ENTER_PYTHON
1501 if (i == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001502 *(e->res) = Tkinter_Error(e->self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001503 }
1504 else {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001505 *(e->res) = Tkapp_ObjectResult(e->self);
1506 }
1507 if (*(e->res) == NULL) {
1508 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001509 }
1510 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001512 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001513done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001514 /* Wake up calling thread. */
1515 Tcl_MutexLock(&call_mutex);
1516 Tcl_ConditionNotify(e->done);
1517 Tcl_MutexUnlock(&call_mutex);
1518 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001519}
1520
Benjamin Peterson5879d412009-03-30 14:51:56 +00001521
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001522/* This is the main entry point for calling a Tcl command.
1523 It supports three cases, with regard to threading:
1524 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1525 the context of the calling thread.
1526 2. Tcl is threaded, caller of the command is in the interpreter thread:
1527 Execute the command in the calling thread. Since the Tcl lock will
1528 not be used, we can merge that with case 1.
1529 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1530 the interpreter thread. Allocation of Tcl objects needs to occur in the
1531 interpreter thread, so we ship the PyObject* args to the target thread,
1532 and perform processing there. */
1533
1534static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001535Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001537 Tcl_Obj *objStore[ARGSZ];
1538 Tcl_Obj **objv = NULL;
1539 int objc, i;
1540 PyObject *res = NULL;
1541 TkappObject *self = (TkappObject*)selfptr;
1542 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001543
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001544 /* If args is a single tuple, replace with contents of tuple */
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001545 if (PyTuple_GET_SIZE(args) == 1) {
1546 PyObject *item = PyTuple_GET_ITEM(args, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 if (PyTuple_Check(item))
1548 args = item;
1549 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1551 /* We cannot call the command directly. Instead, we must
1552 marshal the parameters to the interpreter thread. */
1553 Tkapp_CallEvent *ev;
1554 Tcl_Condition cond = NULL;
1555 PyObject *exc_type, *exc_value, *exc_tb;
1556 if (!WaitForMainloop(self))
1557 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001558 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1559 if (ev == NULL) {
1560 PyErr_NoMemory();
1561 return NULL;
1562 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001563 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1564 ev->self = self;
1565 ev->args = args;
1566 ev->res = &res;
1567 ev->exc_type = &exc_type;
1568 ev->exc_value = &exc_value;
1569 ev->exc_tb = &exc_tb;
1570 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001571
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001572 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001573
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001574 if (res == NULL) {
1575 if (exc_type)
1576 PyErr_Restore(exc_type, exc_value, exc_tb);
1577 else
1578 PyErr_SetObject(Tkinter_TclError, exc_value);
1579 }
1580 Tcl_ConditionFinalize(&cond);
1581 }
1582 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001583 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001584
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001585 objv = Tkapp_CallArgs(args, objStore, &objc);
1586 if (!objv)
1587 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001588
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001589 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001590
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001591 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001593 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001594
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001595 if (i == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001596 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001597 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001598 res = Tkapp_ObjectResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001600 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001602 Tkapp_CallDeallocArgs(objv, objStore, objc);
1603 }
1604 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001605}
1606
1607
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001608/*[clinic input]
1609_tkinter.tkapp.eval
1610
1611 script: str
1612 /
1613
1614[clinic start generated code]*/
1615
Barry Warsawfa701a81997-01-16 00:15:11 +00001616static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001617_tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1618/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001619{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001620 PyObject *res = NULL;
1621 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001622
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001623 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001624 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001625
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001626 ENTER_TCL
1627 err = Tcl_Eval(Tkapp_Interp(self), script);
1628 ENTER_OVERLAP
1629 if (err == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001630 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001631 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001632 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001633 LEAVE_OVERLAP_TCL
1634 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001635}
1636
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001637/*[clinic input]
1638_tkinter.tkapp.evalfile
1639
1640 fileName: str
1641 /
1642
1643[clinic start generated code]*/
1644
Guido van Rossum18468821994-06-20 07:49:28 +00001645static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001646_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1647/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001648{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001649 PyObject *res = NULL;
1650 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001651
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001652 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001653 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001654
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001655 ENTER_TCL
1656 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1657 ENTER_OVERLAP
1658 if (err == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001659 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001660 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001661 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001662 LEAVE_OVERLAP_TCL
1663 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001664}
1665
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001666/*[clinic input]
1667_tkinter.tkapp.record
1668
1669 script: str
1670 /
1671
1672[clinic start generated code]*/
1673
Guido van Rossum18468821994-06-20 07:49:28 +00001674static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001675_tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1676/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001677{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001678 PyObject *res = NULL;
1679 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001680
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001681 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001682 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001684 ENTER_TCL
1685 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1686 ENTER_OVERLAP
1687 if (err == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001688 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001689 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001690 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001691 LEAVE_OVERLAP_TCL
1692 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001693}
1694
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001695/*[clinic input]
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001696_tkinter.tkapp.adderrorinfo
Guido van Rossum18468821994-06-20 07:49:28 +00001697
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001698 msg: str
1699 /
1700
1701[clinic start generated code]*/
1702
1703static PyObject *
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001704_tkinter_tkapp_adderrorinfo_impl(TkappObject *self, const char *msg)
1705/*[clinic end generated code: output=52162eaca2ee53cb input=f4b37aec7c7e8c77]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001706{
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001707 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001708 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001709
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001710 ENTER_TCL
1711 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1712 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001713
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001714 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001715}
1716
Barry Warsawfa701a81997-01-16 00:15:11 +00001717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001718
Guido van Rossum18468821994-06-20 07:49:28 +00001719/** Tcl Variable **/
1720
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001721typedef PyObject* (*EventFunc)(TkappObject *, PyObject *, int);
Benjamin Peterson5879d412009-03-30 14:51:56 +00001722
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001723TCL_DECLARE_MUTEX(var_mutex)
1724
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001725typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001726 Tcl_Event ev; /* must be first */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001727 TkappObject *self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001728 PyObject *args;
1729 int flags;
1730 EventFunc func;
1731 PyObject **res;
1732 PyObject **exc_type;
1733 PyObject **exc_val;
1734 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001735} VarEvent;
1736
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001737/*[python]
1738
1739class varname_converter(CConverter):
1740 type = 'const char *'
1741 converter = 'varname_converter'
1742
1743[python]*/
1744/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1745
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001746static int
1747varname_converter(PyObject *in, void *_out)
1748{
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +02001749 const char *s;
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001750 const char **out = (const char**)_out;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001751 if (PyBytes_Check(in)) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001752 if (PyBytes_GET_SIZE(in) > INT_MAX) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001753 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1754 return 0;
1755 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001756 s = PyBytes_AS_STRING(in);
1757 if (strlen(s) != (size_t)PyBytes_GET_SIZE(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001758 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001759 return 0;
1760 }
1761 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001762 return 1;
1763 }
1764 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001765 Py_ssize_t size;
1766 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001767 if (s == NULL) {
1768 return 0;
1769 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001770 if (size > INT_MAX) {
1771 PyErr_SetString(PyExc_OverflowError, "string is too long");
1772 return 0;
1773 }
Victor Stinner706768c2014-08-16 01:03:39 +02001774 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001775 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001776 return 0;
1777 }
1778 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001779 return 1;
1780 }
1781 if (PyTclObject_Check(in)) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001782 *out = Tcl_GetString(((PyTclObject *)in)->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001783 return 1;
1784 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001785 PyErr_Format(PyExc_TypeError,
1786 "must be str, bytes or Tcl_Obj, not %.50s",
Victor Stinnerdaa97562020-02-07 03:37:06 +01001787 Py_TYPE(in)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001788 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001789}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001790
Benjamin Peterson5879d412009-03-30 14:51:56 +00001791
Martin v. Löwis59683e82008-06-13 07:50:45 +00001792static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001793var_perform(VarEvent *ev)
1794{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001795 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1796 if (!*(ev->res)) {
1797 PyObject *exc, *val, *tb;
1798 PyErr_Fetch(&exc, &val, &tb);
1799 PyErr_NormalizeException(&exc, &val, &tb);
1800 *(ev->exc_type) = exc;
1801 *(ev->exc_val) = val;
Serhiy Storchaka3ec5f422016-10-28 12:14:34 +03001802 Py_XDECREF(tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001803 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001804
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001805}
1806
1807static int
1808var_proc(VarEvent* ev, int flags)
1809{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001810 ENTER_PYTHON
1811 var_perform(ev);
1812 Tcl_MutexLock(&var_mutex);
1813 Tcl_ConditionNotify(ev->cond);
1814 Tcl_MutexUnlock(&var_mutex);
1815 LEAVE_PYTHON
1816 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001817}
1818
Benjamin Peterson5879d412009-03-30 14:51:56 +00001819
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001820static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001821var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001822{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001823 TkappObject *self = (TkappObject*)selfptr;
1824 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001825 VarEvent *ev;
1826 PyObject *res, *exc_type, *exc_val;
1827 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001828
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001829 /* The current thread is not the interpreter thread. Marshal
1830 the call to the interpreter thread, then wait for
1831 completion. */
1832 if (!WaitForMainloop(self))
1833 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001834
Serhiy Storchaka07940882014-09-11 10:38:54 +03001835 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1836 if (ev == NULL) {
1837 PyErr_NoMemory();
1838 return NULL;
1839 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001840 ev->self = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001841 ev->args = args;
1842 ev->flags = flags;
1843 ev->func = func;
1844 ev->res = &res;
1845 ev->exc_type = &exc_type;
1846 ev->exc_val = &exc_val;
1847 ev->cond = &cond;
1848 ev->ev.proc = (Tcl_EventProc*)var_proc;
1849 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1850 Tcl_ConditionFinalize(&cond);
1851 if (!res) {
1852 PyErr_SetObject(exc_type, exc_val);
1853 Py_DECREF(exc_type);
1854 Py_DECREF(exc_val);
1855 return NULL;
1856 }
1857 return res;
1858 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001859 /* Tcl is not threaded, or this is the interpreter thread. */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001860 return func(self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001861}
1862
Guido van Rossum18468821994-06-20 07:49:28 +00001863static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001864SetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001865{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001866 const char *name1, *name2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001867 PyObject *newValue;
1868 PyObject *res = NULL;
1869 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001870
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001871 switch (PyTuple_GET_SIZE(args)) {
1872 case 2:
1873 if (!PyArg_ParseTuple(args, "O&O:setvar",
1874 varname_converter, &name1, &newValue))
1875 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001876 /* XXX Acquire tcl lock??? */
1877 newval = AsObj(newValue);
1878 if (newval == NULL)
1879 return NULL;
1880 ENTER_TCL
1881 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1882 newval, flags);
1883 ENTER_OVERLAP
1884 if (!ok)
1885 Tkinter_Error(self);
1886 else {
1887 res = Py_None;
1888 Py_INCREF(res);
1889 }
1890 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001891 break;
1892 case 3:
1893 if (!PyArg_ParseTuple(args, "ssO:setvar",
1894 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001895 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001896 CHECK_STRING_LENGTH(name1);
1897 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001898 /* XXX must hold tcl lock already??? */
1899 newval = AsObj(newValue);
1900 ENTER_TCL
1901 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1902 ENTER_OVERLAP
1903 if (!ok)
1904 Tkinter_Error(self);
1905 else {
1906 res = Py_None;
1907 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001908 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001909 LEAVE_OVERLAP_TCL
1910 break;
1911 default:
1912 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1913 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001914 }
1915 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001916}
1917
1918static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001919Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001920{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001921 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001922}
1923
1924static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001925Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001926{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001927 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001928}
1929
Barry Warsawfa701a81997-01-16 00:15:11 +00001930
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001931
Guido van Rossum18468821994-06-20 07:49:28 +00001932static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001933GetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001934{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001935 const char *name1, *name2=NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001936 PyObject *res = NULL;
1937 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001938
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001939 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1940 varname_converter, &name1, &name2))
1941 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001942
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001943 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001944 ENTER_TCL
1945 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1946 ENTER_OVERLAP
1947 if (tres == NULL) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001948 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001949 } else {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001950 if (self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001951 res = FromObj(self, tres);
1952 }
1953 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001954 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001955 }
1956 }
1957 LEAVE_OVERLAP_TCL
1958 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001959}
1960
1961static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001962Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001963{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001964 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001965}
1966
1967static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001968Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001969{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001970 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001971}
1972
Barry Warsawfa701a81997-01-16 00:15:11 +00001973
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001974
Guido van Rossum18468821994-06-20 07:49:28 +00001975static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001976UnsetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001977{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001978 char *name1, *name2=NULL;
1979 int code;
1980 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001981
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001982 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1983 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001984
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001985 CHECK_STRING_LENGTH(name1);
1986 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001987 ENTER_TCL
1988 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1989 ENTER_OVERLAP
1990 if (code == TCL_ERROR)
1991 res = Tkinter_Error(self);
1992 else {
1993 Py_INCREF(Py_None);
1994 res = Py_None;
1995 }
1996 LEAVE_OVERLAP_TCL
1997 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001998}
1999
2000static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002001Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002002{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002003 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00002004}
2005
2006static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002007Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002008{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002009 return var_invoke(UnsetVar, self, args,
2010 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00002011}
2012
Barry Warsawfa701a81997-01-16 00:15:11 +00002013
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002014
Guido van Rossum18468821994-06-20 07:49:28 +00002015/** Tcl to Python **/
2016
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002017/*[clinic input]
2018_tkinter.tkapp.getint
2019
2020 arg: object
2021 /
2022
2023[clinic start generated code]*/
2024
Guido van Rossum18468821994-06-20 07:49:28 +00002025static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002026_tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
2027/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002028{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002029 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002030 Tcl_Obj *value;
2031 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00002032
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002033 if (PyLong_Check(arg)) {
2034 Py_INCREF(arg);
2035 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002036 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002037
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002038 if (PyTclObject_Check(arg)) {
2039 value = ((PyTclObject*)arg)->value;
2040 Tcl_IncrRefCount(value);
2041 }
2042 else {
2043 if (!PyArg_Parse(arg, "s:getint", &s))
2044 return NULL;
2045 CHECK_STRING_LENGTH(s);
2046 value = Tcl_NewStringObj(s, -1);
2047 if (value == NULL)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002048 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002049 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002050 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
2051 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
2052
2053 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
2054 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
2055 */
Andrew York003708b2020-05-15 03:43:58 -07002056#ifdef HAVE_LIBTOMMATH
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002057 result = fromBignumObj(self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002058#else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002059 result = fromWideIntObj(self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002060#endif
2061 Tcl_DecrRefCount(value);
2062 if (result != NULL || PyErr_Occurred())
2063 return result;
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002064 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00002065}
2066
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002067/*[clinic input]
2068_tkinter.tkapp.getdouble
2069
2070 arg: object
2071 /
2072
2073[clinic start generated code]*/
2074
Guido van Rossum18468821994-06-20 07:49:28 +00002075static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002076_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
2077/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002078{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002079 char *s;
2080 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00002081
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002082 if (PyFloat_Check(arg)) {
2083 Py_INCREF(arg);
2084 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002085 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002086
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002087 if (PyNumber_Check(arg)) {
2088 return PyNumber_Float(arg);
2089 }
2090
2091 if (PyTclObject_Check(arg)) {
2092 if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
2093 ((PyTclObject*)arg)->value,
2094 &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002095 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002096 return PyFloat_FromDouble(v);
2097 }
2098
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002099 if (!PyArg_Parse(arg, "s:getdouble", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002100 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002101 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002102 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002103 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002104 return PyFloat_FromDouble(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002105}
2106
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002107/*[clinic input]
2108_tkinter.tkapp.getboolean
2109
2110 arg: object
2111 /
2112
2113[clinic start generated code]*/
2114
Guido van Rossum18468821994-06-20 07:49:28 +00002115static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002116_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
2117/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002118{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002119 char *s;
2120 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002121
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002122 if (PyLong_Check(arg)) { /* int or bool */
2123 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002124 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002125
2126 if (PyTclObject_Check(arg)) {
2127 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2128 ((PyTclObject*)arg)->value,
2129 &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002130 return Tkinter_Error(self);
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002131 return PyBool_FromLong(v);
2132 }
2133
2134 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002135 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002136 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002137 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002138 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002139 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002140}
2141
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002142/*[clinic input]
2143_tkinter.tkapp.exprstring
2144
2145 s: str
2146 /
2147
2148[clinic start generated code]*/
2149
Guido van Rossum18468821994-06-20 07:49:28 +00002150static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002151_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2152/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002153{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002154 PyObject *res = NULL;
2155 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002156
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002157 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002158 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002159
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 ENTER_TCL
2161 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2162 ENTER_OVERLAP
2163 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002164 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002165 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002166 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002167 LEAVE_OVERLAP_TCL
2168 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002169}
2170
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002171/*[clinic input]
2172_tkinter.tkapp.exprlong
2173
2174 s: str
2175 /
2176
2177[clinic start generated code]*/
2178
Guido van Rossum18468821994-06-20 07:49:28 +00002179static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002180_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2181/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002182{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002183 PyObject *res = NULL;
2184 int retval;
2185 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002186
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002187 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002188 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002189
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002190 ENTER_TCL
2191 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2192 ENTER_OVERLAP
2193 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002194 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002195 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002196 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 LEAVE_OVERLAP_TCL
2198 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002199}
2200
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002201/*[clinic input]
2202_tkinter.tkapp.exprdouble
2203
2204 s: str
2205 /
2206
2207[clinic start generated code]*/
2208
Guido van Rossum18468821994-06-20 07:49:28 +00002209static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002210_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2211/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002212{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002213 PyObject *res = NULL;
2214 double v;
2215 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002216
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002217 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002218 CHECK_TCL_APPARTMENT;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002219 ENTER_TCL
2220 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2221 ENTER_OVERLAP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002222 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002223 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002224 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002225 res = PyFloat_FromDouble(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002226 LEAVE_OVERLAP_TCL
2227 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002228}
2229
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002230/*[clinic input]
2231_tkinter.tkapp.exprboolean
2232
2233 s: str
2234 /
2235
2236[clinic start generated code]*/
2237
Guido van Rossum18468821994-06-20 07:49:28 +00002238static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002239_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2240/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002241{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002242 PyObject *res = NULL;
2243 int retval;
2244 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002245
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002246 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002247 CHECK_TCL_APPARTMENT;
2248 ENTER_TCL
2249 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2250 ENTER_OVERLAP
2251 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002252 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002253 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002254 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002255 LEAVE_OVERLAP_TCL
2256 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002257}
2258
Barry Warsawfa701a81997-01-16 00:15:11 +00002259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002260
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002261/*[clinic input]
2262_tkinter.tkapp.splitlist
2263
2264 arg: object
2265 /
2266
2267[clinic start generated code]*/
2268
Guido van Rossum18468821994-06-20 07:49:28 +00002269static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002270_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2271/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002272{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002273 char *list;
2274 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002275 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002276 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002277 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002278
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002279 if (PyTclObject_Check(arg)) {
2280 int objc;
2281 Tcl_Obj **objv;
2282 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2283 ((PyTclObject*)arg)->value,
2284 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002285 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002286 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002287 if (!(v = PyTuple_New(objc)))
2288 return NULL;
2289 for (i = 0; i < objc; i++) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002290 PyObject *s = FromObj(self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002291 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002292 Py_DECREF(v);
2293 return NULL;
2294 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002295 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002296 }
2297 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002298 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002299 if (PyTuple_Check(arg)) {
2300 Py_INCREF(arg);
2301 return arg;
2302 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002303 if (PyList_Check(arg)) {
2304 return PySequence_Tuple(arg);
2305 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002306
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002307 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002308 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002309
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002310 if (strlen(list) >= INT_MAX) {
2311 PyErr_SetString(PyExc_OverflowError, "string is too long");
2312 PyMem_Free(list);
2313 return NULL;
2314 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002315 if (Tcl_SplitList(Tkapp_Interp(self), list,
2316 &argc, &argv) == TCL_ERROR) {
2317 PyMem_Free(list);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002318 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002319 }
Guido van Rossum18468821994-06-20 07:49:28 +00002320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002321 if (!(v = PyTuple_New(argc)))
2322 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002323
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002324 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002325 PyObject *s = unicodeFromTclString(argv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002326 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002327 Py_DECREF(v);
2328 v = NULL;
2329 goto finally;
2330 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002331 PyTuple_SET_ITEM(v, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002332 }
Guido van Rossum18468821994-06-20 07:49:28 +00002333
Barry Warsawfa701a81997-01-16 00:15:11 +00002334 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002335 ckfree(FREECAST argv);
2336 PyMem_Free(list);
2337 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002338}
2339
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002340/*[clinic input]
2341_tkinter.tkapp.split
2342
2343 arg: object
2344 /
2345
2346[clinic start generated code]*/
2347
Guido van Rossum18468821994-06-20 07:49:28 +00002348static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002349_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2350/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002351{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002352 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002353 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002354
Serhiy Storchakad05b0002019-10-08 14:31:35 +03002355 if (PyErr_WarnEx(PyExc_DeprecationWarning,
2356 "split() is deprecated; consider using splitlist() instead", 1))
2357 {
2358 return NULL;
2359 }
2360
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002361 if (PyTclObject_Check(arg)) {
2362 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2363 int objc;
2364 Tcl_Obj **objv;
2365 int i;
2366 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2367 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002368 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002369 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002370 if (objc == 0)
2371 return PyUnicode_FromString("");
2372 if (objc == 1)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002373 return FromObj(self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002374 if (!(v = PyTuple_New(objc)))
2375 return NULL;
2376 for (i = 0; i < objc; i++) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002377 PyObject *s = FromObj(self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002378 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002379 Py_DECREF(v);
2380 return NULL;
2381 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002382 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002383 }
2384 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002385 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002386 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002387 return SplitObj(arg);
2388
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002389 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002390 return NULL;
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002391 if (strlen(list) >= INT_MAX) {
2392 PyErr_SetString(PyExc_OverflowError, "string is too long");
2393 PyMem_Free(list);
2394 return NULL;
2395 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002396 v = Split(list);
2397 PyMem_Free(list);
2398 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002399}
2400
Barry Warsawfa701a81997-01-16 00:15:11 +00002401
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002402
Guido van Rossum18468821994-06-20 07:49:28 +00002403/** Tcl Command **/
2404
Guido van Rossum00d93061998-05-28 23:06:38 +00002405/* Client data struct */
2406typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 PyObject *self;
2408 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002409} PythonCmd_ClientData;
2410
2411static int
Fred Drake509d79a2000-07-08 04:04:38 +00002412PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002413{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002414 errorInCmd = 1;
2415 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2416 LEAVE_PYTHON
2417 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002418}
2419
Guido van Rossum18468821994-06-20 07:49:28 +00002420/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002421 * function or method.
2422 */
Guido van Rossum18468821994-06-20 07:49:28 +00002423static int
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002424PythonCmd(ClientData clientData, Tcl_Interp *interp,
2425 int objc, Tcl_Obj *const objv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002426{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002427 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002428 PyObject *args, *res;
2429 int i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002430 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002431
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002432 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002433
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002434 /* Create argument tuple (objv1, ..., objvN) */
2435 if (!(args = PyTuple_New(objc - 1)))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002436 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002437
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002438 for (i = 0; i < (objc - 1); i++) {
2439 PyObject *s = unicodeFromTclObj(objv[i + 1]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002440 if (!s) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002441 Py_DECREF(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002442 return PythonCmd_Error(interp);
2443 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002444 PyTuple_SET_ITEM(args, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002445 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002446
2447 res = PyObject_Call(data->func, args, NULL);
2448 Py_DECREF(args);
Guido van Rossum18468821994-06-20 07:49:28 +00002449
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002450 if (res == NULL)
2451 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002452
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002453 obj_res = AsObj(res);
2454 if (obj_res == NULL) {
2455 Py_DECREF(res);
2456 return PythonCmd_Error(interp);
2457 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002458 Tcl_SetObjResult(interp, obj_res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002459 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002461 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002462
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002463 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +00002464}
2465
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002466
Guido van Rossum18468821994-06-20 07:49:28 +00002467static void
Fred Drake509d79a2000-07-08 04:04:38 +00002468PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002469{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002470 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002471
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002472 ENTER_PYTHON
2473 Py_XDECREF(data->self);
2474 Py_XDECREF(data->func);
2475 PyMem_DEL(data);
2476 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002477}
2478
Barry Warsawfa701a81997-01-16 00:15:11 +00002479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002480
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002481
2482TCL_DECLARE_MUTEX(command_mutex)
2483
2484typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002485 Tcl_Event ev;
2486 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002487 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002488 int create;
2489 int *status;
2490 ClientData *data;
2491 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002492} CommandEvent;
2493
2494static int
2495Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002496{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002497 if (ev->create)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002498 *ev->status = Tcl_CreateObjCommand(
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002499 ev->interp, ev->name, PythonCmd,
2500 ev->data, PythonCmdDelete) == NULL;
2501 else
2502 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2503 Tcl_MutexLock(&command_mutex);
2504 Tcl_ConditionNotify(ev->done);
2505 Tcl_MutexUnlock(&command_mutex);
2506 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002507}
2508
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002509/*[clinic input]
2510_tkinter.tkapp.createcommand
2511
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002512 name: str
2513 func: object
2514 /
2515
2516[clinic start generated code]*/
2517
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002518static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002519_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2520 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002521/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002522{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002523 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002524 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002525
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002526 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002527 if (!PyCallable_Check(func)) {
2528 PyErr_SetString(PyExc_TypeError, "command not callable");
2529 return NULL;
2530 }
Guido van Rossum18468821994-06-20 07:49:28 +00002531
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002532 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2533 !WaitForMainloop(self))
2534 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002535
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002536 data = PyMem_NEW(PythonCmd_ClientData, 1);
2537 if (!data)
2538 return PyErr_NoMemory();
2539 Py_INCREF(self);
2540 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002541 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002542 data->func = func;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002543 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2544 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002545 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2546 if (ev == NULL) {
2547 PyErr_NoMemory();
2548 PyMem_DEL(data);
2549 return NULL;
2550 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002551 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2552 ev->interp = self->interp;
2553 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002554 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002555 ev->data = (ClientData)data;
2556 ev->status = &err;
2557 ev->done = &cond;
2558 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2559 Tcl_ConditionFinalize(&cond);
2560 }
2561 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002562 {
2563 ENTER_TCL
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002564 err = Tcl_CreateObjCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002565 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002566 (ClientData)data, PythonCmdDelete) == NULL;
2567 LEAVE_TCL
2568 }
2569 if (err) {
2570 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2571 PyMem_DEL(data);
2572 return NULL;
2573 }
Guido van Rossum18468821994-06-20 07:49:28 +00002574
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002575 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002576}
2577
Barry Warsawfa701a81997-01-16 00:15:11 +00002578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002580/*[clinic input]
2581_tkinter.tkapp.deletecommand
2582
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002583 name: str
2584 /
2585
2586[clinic start generated code]*/
2587
Guido van Rossum18468821994-06-20 07:49:28 +00002588static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002589_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002590/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002591{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002592 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002593
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002594 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002595
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002596 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2597 Tcl_Condition cond = NULL;
2598 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002599 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2600 if (ev == NULL) {
2601 PyErr_NoMemory();
2602 return NULL;
2603 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002604 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2605 ev->interp = self->interp;
2606 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002607 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002608 ev->status = &err;
2609 ev->done = &cond;
2610 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2611 &command_mutex);
2612 Tcl_ConditionFinalize(&cond);
2613 }
2614 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002615 {
2616 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002617 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002618 LEAVE_TCL
2619 }
2620 if (err == -1) {
2621 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2622 return NULL;
2623 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002624 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002625}
2626
Barry Warsawfa701a81997-01-16 00:15:11 +00002627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002628
Guido van Rossum00d93061998-05-28 23:06:38 +00002629#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002630/** File Handler **/
2631
Guido van Rossum00d93061998-05-28 23:06:38 +00002632typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002633 PyObject *func;
2634 PyObject *file;
2635 int id;
2636 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002637} FileHandler_ClientData;
2638
2639static FileHandler_ClientData *HeadFHCD;
2640
2641static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002642NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002643{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002644 FileHandler_ClientData *p;
2645 p = PyMem_NEW(FileHandler_ClientData, 1);
2646 if (p != NULL) {
2647 Py_XINCREF(func);
2648 Py_XINCREF(file);
2649 p->func = func;
2650 p->file = file;
2651 p->id = id;
2652 p->next = HeadFHCD;
2653 HeadFHCD = p;
2654 }
2655 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002656}
2657
2658static void
Fred Drake509d79a2000-07-08 04:04:38 +00002659DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002660{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002661 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002662
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002663 pp = &HeadFHCD;
2664 while ((p = *pp) != NULL) {
2665 if (p->id == id) {
2666 *pp = p->next;
2667 Py_XDECREF(p->func);
2668 Py_XDECREF(p->file);
2669 PyMem_DEL(p);
2670 }
2671 else
2672 pp = &p->next;
2673 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002674}
2675
Guido van Rossuma597dde1995-01-10 20:56:29 +00002676static void
Fred Drake509d79a2000-07-08 04:04:38 +00002677FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002678{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002679 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
INADA Naoki72dccde2017-02-16 09:26:01 +09002680 PyObject *func, *file, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002682 ENTER_PYTHON
2683 func = data->func;
2684 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002685
INADA Naoki72dccde2017-02-16 09:26:01 +09002686 res = PyObject_CallFunction(func, "Oi", file, mask);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002687 if (res == NULL) {
2688 errorInCmd = 1;
2689 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2690 }
2691 Py_XDECREF(res);
2692 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002693}
2694
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002695/*[clinic input]
2696_tkinter.tkapp.createfilehandler
2697
2698 file: object
2699 mask: int
2700 func: object
2701 /
2702
2703[clinic start generated code]*/
2704
Guido van Rossum18468821994-06-20 07:49:28 +00002705static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002706_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2707 int mask, PyObject *func)
2708/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002709{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002710 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002711 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002712
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002713 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002714
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002715 tfile = PyObject_AsFileDescriptor(file);
2716 if (tfile < 0)
2717 return NULL;
2718 if (!PyCallable_Check(func)) {
2719 PyErr_SetString(PyExc_TypeError, "bad argument list");
2720 return NULL;
2721 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002722
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002723 data = NewFHCD(func, file, tfile);
2724 if (data == NULL)
2725 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002726
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002727 /* Ought to check for null Tcl_File object... */
2728 ENTER_TCL
2729 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2730 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002731 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002732}
2733
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002734/*[clinic input]
2735_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002736
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002737 file: object
2738 /
2739
2740[clinic start generated code]*/
2741
2742static PyObject *
2743_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2744/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2745{
2746 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002747
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002748 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002749
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002750 tfile = PyObject_AsFileDescriptor(file);
2751 if (tfile < 0)
2752 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002753
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002754 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002755
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002756 /* Ought to check for null Tcl_File object... */
2757 ENTER_TCL
2758 Tcl_DeleteFileHandler(tfile);
2759 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002760 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002761}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002762#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002763
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002764
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002765/**** Tktt Object (timer token) ****/
2766
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002767static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002768
Guido van Rossum00d93061998-05-28 23:06:38 +00002769typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002770 PyObject_HEAD
2771 Tcl_TimerToken token;
2772 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002773} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002774
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002775/*[clinic input]
2776_tkinter.tktimertoken.deletetimerhandler
2777
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002778[clinic start generated code]*/
2779
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002780static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002781_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002782/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002783{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002784 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002785 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002786
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002787 if (v->token != NULL) {
2788 Tcl_DeleteTimerHandler(v->token);
2789 v->token = NULL;
2790 }
2791 if (func != NULL) {
2792 v->func = NULL;
2793 Py_DECREF(func);
2794 Py_DECREF(v); /* See Tktt_New() */
2795 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002796 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002797}
2798
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002799static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002800Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002801{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002802 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002803
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002804 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002805 if (v == NULL)
2806 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002807
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002808 Py_INCREF(func);
2809 v->token = NULL;
2810 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002811
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002812 /* Extra reference, deleted when called or when handler is deleted */
2813 Py_INCREF(v);
2814 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002815}
2816
2817static void
Fred Drake509d79a2000-07-08 04:04:38 +00002818Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002819{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002820 TkttObject *v = (TkttObject *)self;
2821 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002822 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002823
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002824 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002825
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002826 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002827 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002828}
2829
Guido van Rossum597ac201998-05-12 14:36:19 +00002830static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002831Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002832{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002833 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002834 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2835 v,
2836 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002837}
2838
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002839/** Timer Handler **/
2840
2841static void
Fred Drake509d79a2000-07-08 04:04:38 +00002842TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002843{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002844 TkttObject *v = (TkttObject *)clientData;
2845 PyObject *func = v->func;
2846 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002847
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002848 if (func == NULL)
2849 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002850
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002851 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002852
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002853 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002854
Victor Stinner2ff58a22019-06-17 14:27:23 +02002855 res = PyObject_CallNoArgs(func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002856 Py_DECREF(func);
2857 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002858
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002859 if (res == NULL) {
2860 errorInCmd = 1;
2861 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2862 }
2863 else
2864 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002865
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002866 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002867}
2868
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002869/*[clinic input]
2870_tkinter.tkapp.createtimerhandler
2871
2872 milliseconds: int
2873 func: object
2874 /
2875
2876[clinic start generated code]*/
2877
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002878static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002879_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2880 PyObject *func)
2881/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002882{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002883 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002884
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002885 if (!PyCallable_Check(func)) {
2886 PyErr_SetString(PyExc_TypeError, "bad argument list");
2887 return NULL;
2888 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002890 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002891
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002892 v = Tktt_New(func);
2893 if (v) {
2894 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2895 (ClientData)v);
2896 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002897
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002898 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002899}
2900
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002901
Guido van Rossum18468821994-06-20 07:49:28 +00002902/** Event Loop **/
2903
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002904/*[clinic input]
2905_tkinter.tkapp.mainloop
2906
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002907 threshold: int = 0
2908 /
2909
2910[clinic start generated code]*/
2911
Guido van Rossum18468821994-06-20 07:49:28 +00002912static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002913_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002914/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002915{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002916 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002917
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002918 CHECK_TCL_APPARTMENT;
2919 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002920
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002921 quitMainLoop = 0;
2922 while (Tk_GetNumMainWindows() > threshold &&
2923 !quitMainLoop &&
2924 !errorInCmd)
2925 {
2926 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002927
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002928 if (self->threaded) {
2929 /* Allow other Python threads to run. */
2930 ENTER_TCL
2931 result = Tcl_DoOneEvent(0);
2932 LEAVE_TCL
2933 }
2934 else {
2935 Py_BEGIN_ALLOW_THREADS
2936 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2937 tcl_tstate = tstate;
2938 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2939 tcl_tstate = NULL;
2940 if(tcl_lock)PyThread_release_lock(tcl_lock);
2941 if (result == 0)
2942 Sleep(Tkinter_busywaitinterval);
2943 Py_END_ALLOW_THREADS
2944 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002945
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002946 if (PyErr_CheckSignals() != 0) {
2947 self->dispatching = 0;
2948 return NULL;
2949 }
2950 if (result < 0)
2951 break;
2952 }
2953 self->dispatching = 0;
2954 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002955
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002956 if (errorInCmd) {
2957 errorInCmd = 0;
2958 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2959 excInCmd = valInCmd = trbInCmd = NULL;
2960 return NULL;
2961 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002962 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002963}
2964
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002965/*[clinic input]
2966_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002967
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002968 flags: int = 0
2969 /
2970
2971[clinic start generated code]*/
2972
2973static PyObject *
2974_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2975/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2976{
2977 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002978
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002979 ENTER_TCL
2980 rv = Tcl_DoOneEvent(flags);
2981 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002982 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002983}
2984
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002985/*[clinic input]
2986_tkinter.tkapp.quit
2987[clinic start generated code]*/
2988
Guido van Rossum062cfb01995-01-10 17:42:51 +00002989static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002990_tkinter_tkapp_quit_impl(TkappObject *self)
2991/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002992{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002993 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002994 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002995}
2996
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002997/*[clinic input]
2998_tkinter.tkapp.interpaddr
2999[clinic start generated code]*/
3000
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003001static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003002_tkinter_tkapp_interpaddr_impl(TkappObject *self)
3003/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003004{
Victor Stinnere1040e22013-09-05 00:22:24 +02003005 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003006}
3007
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003008/*[clinic input]
3009_tkinter.tkapp.loadtk
3010[clinic start generated code]*/
3011
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003012static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003013_tkinter_tkapp_loadtk_impl(TkappObject *self)
3014/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00003015{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003016 Tcl_Interp *interp = Tkapp_Interp(self);
3017 const char * _tk_exists = NULL;
3018 int err;
David Aschere2b4b322004-02-18 05:59:53 +00003019
Guilherme Polob681df42009-02-09 22:33:59 +00003020#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003021 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
3022 * first call failed.
3023 * To avoid the deadlock, we just refuse the second call through
3024 * a static variable.
3025 */
3026 if (tk_load_failed) {
3027 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
3028 return NULL;
3029 }
Guilherme Polob681df42009-02-09 22:33:59 +00003030#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003031
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003032 /* We want to guard against calling Tk_Init() multiple times */
3033 CHECK_TCL_APPARTMENT;
3034 ENTER_TCL
3035 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
3036 ENTER_OVERLAP
3037 if (err == TCL_ERROR) {
3038 /* This sets an exception, but we cannot return right
3039 away because we need to exit the overlap first. */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03003040 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003041 } else {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03003042 _tk_exists = Tcl_GetStringResult(Tkapp_Interp(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003043 }
3044 LEAVE_OVERLAP_TCL
3045 if (err == TCL_ERROR) {
3046 return NULL;
3047 }
3048 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
3049 if (Tk_Init(interp) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03003050 Tkinter_Error(self);
Guilherme Polob681df42009-02-09 22:33:59 +00003051#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003052 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00003053#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003054 return NULL;
3055 }
3056 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003057 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00003058}
Barry Warsawfa701a81997-01-16 00:15:11 +00003059
Martin v. Löwisffad6332002-11-26 09:28:05 +00003060static PyObject *
3061Tkapp_WantObjects(PyObject *self, PyObject *args)
3062{
3063
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003064 int wantobjects = -1;
3065 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3066 return NULL;
3067 if (wantobjects == -1)
3068 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3069 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003070
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003071 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003072}
3073
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003074/*[clinic input]
3075_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003076
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003077[clinic start generated code]*/
3078
3079static PyObject *
3080_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03003081/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003082{
3083 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003084
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003085 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003086}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003088
Guido van Rossum18468821994-06-20 07:49:28 +00003089/**** Tkapp Type Methods ****/
3090
3091static void
Fred Drake509d79a2000-07-08 04:04:38 +00003092Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003093{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003094 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003095 /*CHECK_TCL_APPARTMENT;*/
3096 ENTER_TCL
3097 Tcl_DeleteInterp(Tkapp_Interp(self));
3098 LEAVE_TCL
3099 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003100 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003101 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003102}
3103
Barry Warsawfa701a81997-01-16 00:15:11 +00003104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003105
Guido van Rossum18468821994-06-20 07:49:28 +00003106/**** Tkinter Module ****/
3107
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003108typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003109 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003110 Py_ssize_t size; /* current size */
3111 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003112} FlattenContext;
3113
3114static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003115_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003116{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003117 /* expand tuple to hold (at least) size new items.
3118 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003119
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003120 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003121
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003122 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003123 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003124
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003125 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003126
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003127 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003128}
3129
3130static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003131_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003132{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003133 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003134
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003135 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003136
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003137 if (depth > 1000) {
3138 PyErr_SetString(PyExc_ValueError,
3139 "nesting too deep in _flatten");
3140 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003141 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3142 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003143 /* preallocate (assume no nesting) */
3144 if (context->size + size > context->maxsize &&
3145 !_bump(context, size))
3146 return 0;
3147 /* copy items to output tuple */
3148 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003149 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003150 if (PyList_Check(o) || PyTuple_Check(o)) {
3151 if (!_flatten1(context, o, depth + 1))
3152 return 0;
3153 } else if (o != Py_None) {
3154 if (context->size + 1 > context->maxsize &&
3155 !_bump(context, 1))
3156 return 0;
3157 Py_INCREF(o);
3158 PyTuple_SET_ITEM(context->tuple,
3159 context->size++, o);
3160 }
3161 }
3162 } else {
3163 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3164 return 0;
3165 }
3166 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003167}
3168
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003169/*[clinic input]
3170_tkinter._flatten
3171
3172 item: object
3173 /
3174
3175[clinic start generated code]*/
3176
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003177static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003178_tkinter__flatten(PyObject *module, PyObject *item)
3179/*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003180{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003181 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003182
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003183 context.maxsize = PySequence_Size(item);
3184 if (context.maxsize < 0)
3185 return NULL;
3186 if (context.maxsize == 0)
3187 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003188
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003189 context.tuple = PyTuple_New(context.maxsize);
3190 if (!context.tuple)
3191 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003192
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003193 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003195 if (!_flatten1(&context, item,0))
3196 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003198 if (_PyTuple_Resize(&context.tuple, context.size))
3199 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003200
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003201 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003202}
3203
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003204/*[clinic input]
3205_tkinter.create
3206
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003207 screenName: str(accept={str, NoneType}) = None
3208 baseName: str = ""
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003209 className: str = "Tk"
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003210 interactive: bool(accept={int}) = False
3211 wantobjects: bool(accept={int}) = False
3212 wantTk: bool(accept={int}) = True
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003213 if false, then Tk_Init() doesn't get called
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003214 sync: bool(accept={int}) = False
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003215 if true, then pass -sync to wish
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003216 use: str(accept={str, NoneType}) = None
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003217 if not None, then pass -use to wish
3218 /
3219
3220[clinic start generated code]*/
3221
Guido van Rossum18468821994-06-20 07:49:28 +00003222static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003223_tkinter_create_impl(PyObject *module, const char *screenName,
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003224 const char *baseName, const char *className,
3225 int interactive, int wantobjects, int wantTk, int sync,
3226 const char *use)
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003227/*[clinic end generated code: output=e3315607648e6bb4 input=da9b17ee7358d862]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003228{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003229 /* XXX baseName is not used anymore;
3230 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003231 CHECK_STRING_LENGTH(screenName);
3232 CHECK_STRING_LENGTH(baseName);
3233 CHECK_STRING_LENGTH(className);
3234 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003236 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003237 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003238 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003239}
3240
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003241/*[clinic input]
3242_tkinter.setbusywaitinterval
3243
3244 new_val: int
3245 /
3246
3247Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3248
3249It should be set to a divisor of the maximum time between frames in an animation.
3250[clinic start generated code]*/
3251
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003252static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003253_tkinter_setbusywaitinterval_impl(PyObject *module, int new_val)
3254/*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003255{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003256 if (new_val < 0) {
3257 PyErr_SetString(PyExc_ValueError,
3258 "busywaitinterval must be >= 0");
3259 return NULL;
3260 }
3261 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003262 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003263}
3264
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003265/*[clinic input]
3266_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003267
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003268Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3269[clinic start generated code]*/
3270
3271static int
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003272_tkinter_getbusywaitinterval_impl(PyObject *module)
3273/*[clinic end generated code: output=23b72d552001f5c7 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003274{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003275 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003276}
3277
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003278#include "clinic/_tkinter.c.h"
3279
3280static PyMethodDef Tktt_methods[] =
3281{
3282 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3283 {NULL, NULL}
3284};
3285
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003286static PyType_Slot Tktt_Type_slots[] = {
3287 {Py_tp_dealloc, Tktt_Dealloc},
3288 {Py_tp_repr, Tktt_Repr},
3289 {Py_tp_methods, Tktt_methods},
3290 {0, 0}
3291};
3292
3293static PyType_Spec Tktt_Type_spec = {
3294 "_tkinter.tktimertoken",
3295 sizeof(TkttObject),
3296 0,
3297 Py_TPFLAGS_DEFAULT,
3298 Tktt_Type_slots,
3299};
3300
3301
3302/**** Tkapp Method List ****/
3303
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003304static PyMethodDef Tkapp_methods[] =
3305{
3306 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3307 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3308 {"call", Tkapp_Call, METH_VARARGS},
3309 _TKINTER_TKAPP_EVAL_METHODDEF
3310 _TKINTER_TKAPP_EVALFILE_METHODDEF
3311 _TKINTER_TKAPP_RECORD_METHODDEF
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03003312 _TKINTER_TKAPP_ADDERRORINFO_METHODDEF
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003313 {"setvar", Tkapp_SetVar, METH_VARARGS},
3314 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3315 {"getvar", Tkapp_GetVar, METH_VARARGS},
3316 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3317 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3318 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3319 _TKINTER_TKAPP_GETINT_METHODDEF
3320 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3321 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3322 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3323 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3324 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3325 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3326 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3327 _TKINTER_TKAPP_SPLIT_METHODDEF
3328 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3329 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3330 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3331 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3332 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3333 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3334 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3335 _TKINTER_TKAPP_QUIT_METHODDEF
3336 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3337 _TKINTER_TKAPP_LOADTK_METHODDEF
3338 {NULL, NULL}
3339};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003340
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003341static PyType_Slot Tkapp_Type_slots[] = {
3342 {Py_tp_dealloc, Tkapp_Dealloc},
3343 {Py_tp_methods, Tkapp_methods},
3344 {0, 0}
3345};
3346
3347
3348static PyType_Spec Tkapp_Type_spec = {
3349 "_tkinter.tkapp",
3350 sizeof(TkappObject),
3351 0,
3352 Py_TPFLAGS_DEFAULT,
3353 Tkapp_Type_slots,
3354};
3355
Guido van Rossum18468821994-06-20 07:49:28 +00003356static PyMethodDef moduleMethods[] =
3357{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003358 _TKINTER__FLATTEN_METHODDEF
3359 _TKINTER_CREATE_METHODDEF
3360 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3361 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003362 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003363};
3364
Guido van Rossum7bf15641998-05-22 18:28:17 +00003365#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003366
3367static int stdin_ready = 0;
3368
Guido van Rossumad4db171998-06-13 13:56:28 +00003369#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003370static void
Fred Drake509d79a2000-07-08 04:04:38 +00003371MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003372{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003373 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003374}
Guido van Rossumad4db171998-06-13 13:56:28 +00003375#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003376
Guido van Rossum00d93061998-05-28 23:06:38 +00003377static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003378
Guido van Rossum18468821994-06-20 07:49:28 +00003379static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003380EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003381{
Guido van Rossumad4db171998-06-13 13:56:28 +00003382#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003383 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003384#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003385 PyEval_RestoreThread(event_tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003386 stdin_ready = 0;
3387 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003388#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003389 tfile = fileno(stdin);
3390 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003391#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003392 while (!errorInCmd && !stdin_ready) {
3393 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003394#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003395 if (_kbhit()) {
3396 stdin_ready = 1;
3397 break;
3398 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003399#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003400 Py_BEGIN_ALLOW_THREADS
3401 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3402 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003403
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003404 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003405
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003406 tcl_tstate = NULL;
3407 if(tcl_lock)PyThread_release_lock(tcl_lock);
3408 if (result == 0)
3409 Sleep(Tkinter_busywaitinterval);
3410 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003411
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003412 if (result < 0)
3413 break;
3414 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003415#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003416 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003417#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003418 if (errorInCmd) {
3419 errorInCmd = 0;
3420 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3421 excInCmd = valInCmd = trbInCmd = NULL;
3422 PyErr_Print();
3423 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003424 PyEval_SaveThread();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003425 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003426}
Guido van Rossum18468821994-06-20 07:49:28 +00003427
Guido van Rossum00d93061998-05-28 23:06:38 +00003428#endif
3429
Guido van Rossum7bf15641998-05-22 18:28:17 +00003430static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003431EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003432{
Guido van Rossum00d93061998-05-28 23:06:38 +00003433#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003434 if (PyOS_InputHook == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003435 event_tstate = PyThreadState_Get();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003436 PyOS_InputHook = EventHook;
3437 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003438#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003439}
3440
3441static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003442DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003443{
Guido van Rossum00d93061998-05-28 23:06:38 +00003444#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003445 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3446 PyOS_InputHook = NULL;
3447 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003448#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003449}
3450
Barry Warsawfa701a81997-01-16 00:15:11 +00003451
Martin v. Löwis1a214512008-06-11 05:26:20 +00003452static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003453 PyModuleDef_HEAD_INIT,
3454 "_tkinter",
3455 NULL,
3456 -1,
3457 moduleMethods,
3458 NULL,
3459 NULL,
3460 NULL,
3461 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003462};
3463
Mark Hammond62b1ab12002-07-23 06:31:15 +00003464PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003465PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003466{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003467 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003469 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003470 if (tcl_lock == NULL)
3471 return NULL;
Guido van Rossumae92f011996-08-21 19:03:36 +00003472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003473 m = PyModule_Create(&_tkintermodule);
3474 if (m == NULL)
3475 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003476
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003477 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3478 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003479 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003480 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003481 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003482 Py_INCREF(o);
3483 if (PyModule_AddObject(m, "TclError", o)) {
3484 Py_DECREF(o);
3485 Py_DECREF(m);
3486 return NULL;
3487 }
3488 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003489
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003490 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3491 Py_DECREF(m);
3492 return NULL;
3493 }
3494 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3495 Py_DECREF(m);
3496 return NULL;
3497 }
3498 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3499 Py_DECREF(m);
3500 return NULL;
3501 }
3502 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3503 Py_DECREF(m);
3504 return NULL;
3505 }
3506 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3507 Py_DECREF(m);
3508 return NULL;
3509 }
3510 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3511 Py_DECREF(m);
3512 return NULL;
3513 }
3514 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3515 Py_DECREF(m);
3516 return NULL;
3517 }
3518 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3519 Py_DECREF(m);
3520 return NULL;
3521 }
3522 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3523 Py_DECREF(m);
3524 return NULL;
3525 }
3526 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3527 Py_DECREF(m);
3528 return NULL;
3529 }
3530 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3531 Py_DECREF(m);
3532 return NULL;
3533 }
3534
3535 o = PyType_FromSpec(&Tkapp_Type_spec);
3536 if (o == NULL) {
3537 Py_DECREF(m);
3538 return NULL;
3539 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003540 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003541 if (PyModule_AddObject(m, "TkappType", o)) {
3542 Py_DECREF(o);
3543 Py_DECREF(m);
3544 return NULL;
3545 }
3546 Tkapp_Type = o;
3547
3548 o = PyType_FromSpec(&Tktt_Type_spec);
3549 if (o == NULL) {
3550 Py_DECREF(m);
3551 return NULL;
3552 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003553 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003554 if (PyModule_AddObject(m, "TkttType", o)) {
3555 Py_DECREF(o);
3556 Py_DECREF(m);
3557 return NULL;
3558 }
3559 Tktt_Type = o;
3560
3561 o = PyType_FromSpec(&PyTclObject_Type_spec);
3562 if (o == NULL) {
3563 Py_DECREF(m);
3564 return NULL;
3565 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003566 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003567 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3568 Py_DECREF(o);
3569 Py_DECREF(m);
3570 return NULL;
3571 }
3572 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003573
3574#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003575 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3576 * start waking up. Note that Tcl_FindExecutable will do this, this
3577 * code must be above it! The original warning from
3578 * tkMacOSXAppInit.c is copied below.
3579 *
3580 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3581 * Tcl interpreter for now. It probably should work to do this
3582 * in the other order, but for now it doesn't seem to.
3583 *
3584 */
3585 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003586#endif
3587
3588
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003589 /* This helps the dynamic loader; in Unicode aware Tcl versions
3590 it also helps Tcl find its encodings. */
3591 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3592 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003593 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003594 if (cexe) {
3595#ifdef MS_WINDOWS
3596 int set_var = 0;
3597 PyObject *str_path;
3598 wchar_t *wcs_path;
3599 DWORD ret;
3600
3601 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3602
3603 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3604 str_path = _get_tcl_lib_path();
3605 if (str_path == NULL && PyErr_Occurred()) {
Brandt Bucher289cf0f2019-11-18 06:52:36 -08003606 Py_DECREF(m);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003607 return NULL;
3608 }
3609 if (str_path != NULL) {
3610 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3611 if (wcs_path == NULL) {
Brandt Bucher289cf0f2019-11-18 06:52:36 -08003612 Py_DECREF(m);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003613 return NULL;
3614 }
3615 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3616 set_var = 1;
3617 }
3618 }
3619
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003620 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003621
3622 if (set_var) {
3623 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3624 PyMem_Free(wcs_path);
3625 }
3626#else
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003627 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003628#endif /* MS_WINDOWS */
3629 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003630 Py_XDECREF(cexe);
3631 Py_DECREF(uexe);
3632 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003634 if (PyErr_Occurred()) {
3635 Py_DECREF(m);
3636 return NULL;
3637 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003638
Guido van Rossum43ff8681998-07-14 18:02:13 +00003639#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003640 /* This was not a good idea; through <Destroy> bindings,
3641 Tcl_Finalize() may invoke Python code but at that point the
3642 interpreter and thread state have already been destroyed! */
3643 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003644#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003645 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003646}