blob: 87bc7ae8aeeabc68bba9e8ae3f1144e31589b7cb [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Serhiy Storchaka6716d602014-07-30 19:19:21 +030012 Only Tcl/Tk 8.4 and later are supported. Older versions are not
13 supported. Use Python 3.4 or older if you cannot upgrade your
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000014 Tcl/Tk libraries.
Guido van Rossuma80649b2000-03-28 20:07:05 +000015*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Serhiy Storchaka26861b02015-02-16 20:52:17 +020024#define PY_SSIZE_T_CLEAN
Guido van Rossum35d43371997-08-02 00:09:09 +000025
Guido van Rossum9722ad81995-09-22 23:49:28 +000026#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000027#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000028
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030
Guido van Rossum2a5119b1998-05-29 01:28:40 +000031#ifdef MS_WINDOWS
32#include <windows.h>
33#endif
34
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030035#define CHECK_SIZE(size, elemsize) \
Serhiy Storchaka26861b02015-02-16 20:52:17 +020036 ((size_t)(size) <= Py_MIN((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030037
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000038/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
39 it always; if Tcl is not threaded, the thread functions in
40 Tcl are empty. */
41#define TCL_THREADS
42
Jack Jansencb852442001-12-09 23:15:56 +000043#ifdef TK_FRAMEWORK
44#include <Tcl/tcl.h>
45#include <Tk/tk.h>
46#else
Guido van Rossum18468821994-06-20 07:49:28 +000047#include <tcl.h>
48#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000049#endif
Guido van Rossum18468821994-06-20 07:49:28 +000050
Guilherme Polo2d87e422009-04-10 22:19:09 +000051#include "tkinter.h"
52
Serhiy Storchaka71b49dd2015-04-22 10:59:32 +030053#if TK_HEX_VERSION < 0x08040200
Serhiy Storchaka6716d602014-07-30 19:19:21 +030054#error "Tk older than 8.4 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000055#endif
56
Serhiy Storchaka3af7a382015-04-22 10:53:08 +030057#if TK_HEX_VERSION >= 0x08050208 && TK_HEX_VERSION < 0x08060000 || \
58 TK_HEX_VERSION >= 0x08060200
Serhiy Storchakaea134da2015-04-02 18:46:50 +030059#define HAVE_LIBTOMMAMTH
60#include <tclTomMath.h>
61#endif
62
Jack Janseneddc1442003-11-20 01:44:59 +000063#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000064#define HAVE_CREATEFILEHANDLER
65#endif
66
Guido van Rossum00d93061998-05-28 23:06:38 +000067#ifdef HAVE_CREATEFILEHANDLER
68
Neal Norwitzd948a432006-01-08 01:08:55 +000069/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
70 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
71#ifndef TCL_UNIX_FD
72# ifdef TCL_WIN_SOCKET
73# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
74# else
75# define TCL_UNIX_FD 1
76# endif
77#endif
78
Guido van Rossum00d93061998-05-28 23:06:38 +000079/* Tcl_CreateFileHandler() changed several times; these macros deal with the
80 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
81 Unix, only because Jack added it back); when available on Windows, it only
82 applies to sockets. */
83
Guido van Rossum7bf15641998-05-22 18:28:17 +000084#ifdef MS_WINDOWS
85#define FHANDLETYPE TCL_WIN_SOCKET
86#else
87#define FHANDLETYPE TCL_UNIX_FD
88#endif
89
Guido van Rossum00d93061998-05-28 23:06:38 +000090/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
91 which uses this to handle Tcl events while the user is typing commands. */
92
93#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +000094#define WAIT_FOR_STDIN
95#endif
96
Guido van Rossum00d93061998-05-28 23:06:38 +000097#endif /* HAVE_CREATEFILEHANDLER */
98
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +030099/* Use OS native encoding for converting between Python strings and
100 Tcl objects.
101 On Windows use UTF-16 (or UTF-32 for 32-bit Tcl_UniChar) with the
102 "surrogatepass" error handler for converting to/from Tcl Unicode objects.
103 On Linux use UTF-8 with the "surrogateescape" error handler for converting
104 to/from Tcl String objects. */
105#ifdef MS_WINDOWS
106#define USE_TCL_UNICODE 1
107#else
108#define USE_TCL_UNICODE 0
109#endif
110
111#if PY_LITTLE_ENDIAN
112#define NATIVE_BYTEORDER -1
113#else
114#define NATIVE_BYTEORDER 1
115#endif
116
Guido van Rossumad4db171998-06-13 13:56:28 +0000117#ifdef MS_WINDOWS
118#include <conio.h>
119#define WAIT_FOR_STDIN
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500120
121static PyObject *
122_get_tcl_lib_path()
123{
124 static PyObject *tcl_library_path = NULL;
125 static int already_checked = 0;
126
127 if (already_checked == 0) {
128 PyObject *prefix;
129 struct stat stat_buf;
130 int stat_return_value;
131
132 prefix = PyUnicode_FromWideChar(Py_GetPrefix(), -1);
133 if (prefix == NULL) {
134 return NULL;
135 }
136
137 /* Check expected location for an installed Python first */
138 tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION);
139 if (tcl_library_path == NULL) {
140 return NULL;
141 }
142 tcl_library_path = PyUnicode_Concat(prefix, tcl_library_path);
143 if (tcl_library_path == NULL) {
144 return NULL;
145 }
146 stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
147 if (stat_return_value == -2) {
148 return NULL;
149 }
150 if (stat_return_value == -1) {
151 /* install location doesn't exist, reset errno and see if
152 we're a repository build */
153 errno = 0;
154#ifdef Py_TCLTK_DIR
155 tcl_library_path = PyUnicode_FromString(
156 Py_TCLTK_DIR "\\lib\\tcl" TCL_VERSION);
157 if (tcl_library_path == NULL) {
158 return NULL;
159 }
160 stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
161 if (stat_return_value == -2) {
162 return NULL;
163 }
164 if (stat_return_value == -1) {
165 /* tcltkDir for a repository build doesn't exist either,
166 reset errno and leave Tcl to its own devices */
167 errno = 0;
168 tcl_library_path = NULL;
169 }
170#else
171 tcl_library_path = NULL;
Guido van Rossumad4db171998-06-13 13:56:28 +0000172#endif
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500173 }
174 already_checked = 1;
175 }
176 return tcl_library_path;
177}
178#endif /* MS_WINDOWS */
Guido van Rossumad4db171998-06-13 13:56:28 +0000179
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000180/* The threading situation is complicated. Tcl is not thread-safe, except
181 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000182
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300183 So we need to use a lock around all uses of Tcl. Previously, the
184 Python interpreter lock was used for this. However, this causes
185 problems when other Python threads need to run while Tcl is blocked
186 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000187
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300188 To solve this problem, a separate lock for Tcl is introduced.
189 Holding it is incompatible with holding Python's interpreter lock.
190 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000191
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300192 ENTER_TCL and LEAVE_TCL are brackets, just like
193 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
194 used whenever a call into Tcl is made that could call an event
195 handler, or otherwise affect the state of a Tcl interpreter. These
196 assume that the surrounding code has the Python interpreter lock;
197 inside the brackets, the Python interpreter lock has been released
198 and the lock for Tcl has been acquired.
199
200 Sometimes, it is necessary to have both the Python lock and the Tcl
201 lock. (For example, when transferring data from the Tcl
202 interpreter result to a Python string object.) This can be done by
203 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
204 reacquires the Python lock (and restores the thread state) but
205 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
206 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000207
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000208 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300209 handlers when the handler needs to use Python. Such event handlers
210 are entered while the lock for Tcl is held; the event handler
211 presumably needs to use Python. ENTER_PYTHON releases the lock for
212 Tcl and acquires the Python interpreter lock, restoring the
213 appropriate thread state, and LEAVE_PYTHON releases the Python
214 interpreter lock and re-acquires the lock for Tcl. It is okay for
215 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
216 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000217
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300218 These locks expand to several statements and brackets; they should
219 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000220
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300221 If Tcl is threaded, this approach won't work anymore. The Tcl
222 interpreter is only valid in the thread that created it, and all Tk
223 activity must happen in this thread, also. That means that the
224 mainloop must be invoked in the thread that created the
225 interpreter. Invoking commands from other threads is possible;
226 _tkinter will queue an event for the interpreter thread, which will
227 then execute the command and pass back the result. If the main
228 thread is not in the mainloop, and invoking commands causes an
229 exception; if the main loop is running but not processing events,
230 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000231
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300232 In addition, for a threaded Tcl, a single global tcl_tstate won't
233 be sufficient anymore, since multiple Tcl interpreters may
234 simultaneously dispatch in different threads. So we use the Tcl TLS
235 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000236
Guido van Rossum00d93061998-05-28 23:06:38 +0000237*/
238
Guido van Rossum65d5b571998-12-21 19:32:43 +0000239static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000240
241#ifdef TCL_THREADS
242static Tcl_ThreadDataKey state_key;
243typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300244#define tcl_tstate \
245 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000246#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000247static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000248#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000249
250#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000251 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
252 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000253
254#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300255 tcl_tstate = NULL; \
256 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000257
Guido van Rossum62320c91998-06-15 04:36:09 +0000258#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000259 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000260
261#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000262 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000263
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000264#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000265 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300266 if(tcl_lock) \
267 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000268
269#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270 { PyThreadState *tstate = PyEval_SaveThread(); \
271 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000272
273#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000274 if (((TkappObject *)self)->threaded && \
275 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300276 PyErr_SetString(PyExc_RuntimeError, \
luzpaza5293b42017-11-05 07:37:50 -0600277 "Calling Tcl from different apartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000278 return 0; \
279 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000280
Guido van Rossum97867b21996-08-08 19:09:53 +0000281#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000282#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000283#endif
284
Guido van Rossum18468821994-06-20 07:49:28 +0000285/**** Tkapp Object Declaration ****/
286
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300287static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000288
Guido van Rossum00d93061998-05-28 23:06:38 +0000289typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000290 PyObject_HEAD
291 Tcl_Interp *interp;
292 int wantobjects;
293 int threaded; /* True if tcl_platform[threaded] */
294 Tcl_ThreadId thread_id;
295 int dispatching;
296 /* We cannot include tclInt.h, as this is internal.
297 So we cache interesting types here. */
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200298 const Tcl_ObjType *OldBooleanType;
Zachary Ware037605b2014-08-05 11:54:34 -0500299 const Tcl_ObjType *BooleanType;
300 const Tcl_ObjType *ByteArrayType;
301 const Tcl_ObjType *DoubleType;
302 const Tcl_ObjType *IntType;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300303 const Tcl_ObjType *WideIntType;
304 const Tcl_ObjType *BignumType;
Zachary Ware037605b2014-08-05 11:54:34 -0500305 const Tcl_ObjType *ListType;
306 const Tcl_ObjType *ProcBodyType;
307 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000308} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000309
Guido van Rossum18468821994-06-20 07:49:28 +0000310#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000311
Guido van Rossum35d43371997-08-02 00:09:09 +0000312#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000313(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000314
Barry Warsawfa701a81997-01-16 00:15:11 +0000315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000316
Guido van Rossum18468821994-06-20 07:49:28 +0000317/**** Error Handling ****/
318
319static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000320static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000321static int errorInCmd = 0;
322static PyObject *excInCmd;
323static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000324static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000325
Guilherme Polob681df42009-02-09 22:33:59 +0000326#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000327static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000328#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000330
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300331static PyObject *Tkapp_UnicodeResult(TkappObject *);
332
Guido van Rossum18468821994-06-20 07:49:28 +0000333static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300334Tkinter_Error(TkappObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +0000335{
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300336 PyObject *res = Tkapp_UnicodeResult(self);
337 if (res != NULL) {
338 PyErr_SetObject(Tkinter_TclError, res);
339 Py_DECREF(res);
340 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000341 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000342}
343
Barry Warsawfa701a81997-01-16 00:15:11 +0000344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000345
Guido van Rossum18468821994-06-20 07:49:28 +0000346/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000347
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000348static int Tkinter_busywaitinterval = 20;
349
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000350#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000351
Guido van Rossum00d93061998-05-28 23:06:38 +0000352/* Millisecond sleep() for Unix platforms. */
353
354static void
Fred Drake509d79a2000-07-08 04:04:38 +0000355Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000356{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000357 /* XXX Too bad if you don't have select(). */
358 struct timeval t;
359 t.tv_sec = milli/1000;
360 t.tv_usec = (milli%1000) * 1000;
361 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000362}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000363#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000364
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000365/* Wait up to 1s for the mainloop to come up. */
366
367static int
368WaitForMainloop(TkappObject* self)
369{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000370 int i;
371 for (i = 0; i < 10; i++) {
372 if (self->dispatching)
373 return 1;
374 Py_BEGIN_ALLOW_THREADS
375 Sleep(100);
376 Py_END_ALLOW_THREADS
377 }
378 if (self->dispatching)
379 return 1;
380 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
381 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000382}
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000384
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000385
Guido van Rossum18468821994-06-20 07:49:28 +0000386#define ARGSZ 64
387
Barry Warsawfa701a81997-01-16 00:15:11 +0000388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000389
Guido van Rossum18468821994-06-20 07:49:28 +0000390static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200391unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
392{
393 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300394 if (r != NULL || !PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
395 return r;
396 }
397
398 char *buf = NULL;
399 PyErr_Clear();
400 /* Tcl encodes null character as \xc0\x80 */
401 if (memchr(s, '\xc0', size)) {
402 char *q;
403 const char *e = s + size;
404 q = buf = (char *)PyMem_Malloc(size);
405 if (buf == NULL) {
406 PyErr_NoMemory();
407 return NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200408 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300409 while (s != e) {
410 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
411 *q++ = '\0';
412 s += 2;
413 }
414 else
415 *q++ = *s++;
416 }
417 s = buf;
418 size = q - s;
419 }
420 r = PyUnicode_DecodeUTF8(s, size, "surrogateescape");
421 if (buf != NULL) {
422 PyMem_Free(buf);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200423 }
424 return r;
425}
426
427static PyObject *
428unicodeFromTclString(const char *s)
429{
430 return unicodeFromTclStringAndSize(s, strlen(s));
431}
432
433static PyObject *
434unicodeFromTclObj(Tcl_Obj *value)
435{
436 int len;
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300437#if USE_TCL_UNICODE
438 int byteorder = NATIVE_BYTEORDER;
439 const Tcl_UniChar *u = Tcl_GetUnicodeFromObj(value, &len);
440 if (sizeof(Tcl_UniChar) == 2)
441 return PyUnicode_DecodeUTF16((const char *)u, len * 2,
442 "surrogatepass", &byteorder);
443 else if (sizeof(Tcl_UniChar) == 4)
444 return PyUnicode_DecodeUTF32((const char *)u, len * 4,
445 "surrogatepass", &byteorder);
446 else
447 Py_UNREACHABLE();
448#else
449 const char *s = Tcl_GetStringFromObj(value, &len);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200450 return unicodeFromTclStringAndSize(s, len);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300451#endif
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200452}
453
454
455static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300456Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000457{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000458 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300459 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000460 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000462 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300463 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000464 }
Guido van Rossum18468821994-06-20 07:49:28 +0000465
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
467 /* Not a list.
468 * Could be a quoted string containing funnies, e.g. {"}.
469 * Return the string itself.
470 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200471 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000472 }
Guido van Rossum18468821994-06-20 07:49:28 +0000473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000474 if (argc == 0)
475 v = PyUnicode_FromString("");
476 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200477 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000478 else if ((v = PyTuple_New(argc)) != NULL) {
479 int i;
480 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000481
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000482 for (i = 0; i < argc; i++) {
483 if ((w = Split(argv[i])) == NULL) {
484 Py_DECREF(v);
485 v = NULL;
486 break;
487 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300488 PyTuple_SET_ITEM(v, i, w);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000489 }
490 }
491 Tcl_Free(FREECAST argv);
492 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000493}
494
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300495/* In some cases, Tcl will still return strings that are supposed to
496 be lists. SplitObj walks through a nested tuple, finding string
497 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000498
Martin v. Löwis59683e82008-06-13 07:50:45 +0000499static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000500SplitObj(PyObject *arg)
501{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000502 if (PyTuple_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200503 Py_ssize_t i, size;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000504 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000505
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300506 size = PyTuple_GET_SIZE(arg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000507 result = NULL;
508 /* Recursively invoke SplitObj for all tuple items.
509 If this does not return a new object, no action is
510 needed. */
511 for(i = 0; i < size; i++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300512 elem = PyTuple_GET_ITEM(arg, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513 newelem = SplitObj(elem);
514 if (!newelem) {
515 Py_XDECREF(result);
516 return NULL;
517 }
518 if (!result) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200519 Py_ssize_t k;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000520 if (newelem == elem) {
521 Py_DECREF(newelem);
522 continue;
523 }
524 result = PyTuple_New(size);
525 if (!result)
526 return NULL;
527 for(k = 0; k < i; k++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300528 elem = PyTuple_GET_ITEM(arg, k);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000529 Py_INCREF(elem);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300530 PyTuple_SET_ITEM(result, k, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000531 }
532 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300533 PyTuple_SET_ITEM(result, i, newelem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000534 }
535 if (result)
536 return result;
537 /* Fall through, returning arg. */
538 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300539 else if (PyList_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200540 Py_ssize_t i, size;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300541 PyObject *elem, *newelem, *result;
542
543 size = PyList_GET_SIZE(arg);
544 result = PyTuple_New(size);
545 if (!result)
546 return NULL;
547 /* Recursively invoke SplitObj for all list items. */
548 for(i = 0; i < size; i++) {
549 elem = PyList_GET_ITEM(arg, i);
550 newelem = SplitObj(elem);
551 if (!newelem) {
552 Py_XDECREF(result);
553 return NULL;
554 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300555 PyTuple_SET_ITEM(result, i, newelem);
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300556 }
557 return result;
558 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300559 else if (PyUnicode_Check(arg)) {
560 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300561 const char **argv;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200562 const char *list = PyUnicode_AsUTF8(arg);
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300563
564 if (list == NULL ||
565 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
566 Py_INCREF(arg);
567 return arg;
568 }
569 Tcl_Free(FREECAST argv);
570 if (argc > 1)
571 return Split(list);
572 /* Fall through, returning arg. */
573 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000574 else if (PyBytes_Check(arg)) {
575 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300576 const char **argv;
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300577 char *list = PyBytes_AS_STRING(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000579 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
580 Py_INCREF(arg);
581 return arg;
582 }
583 Tcl_Free(FREECAST argv);
584 if (argc > 1)
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300585 return Split(PyBytes_AS_STRING(arg));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 /* Fall through, returning arg. */
587 }
588 Py_INCREF(arg);
589 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000590}
Barry Warsawfa701a81997-01-16 00:15:11 +0000591
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000592
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +0300593/*[clinic input]
594module _tkinter
595class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec"
596class _tkinter.Tcl_Obj "PyTclObject *" "&PyTclObject_Type_spec"
597class _tkinter.tktimertoken "TkttObject *" "&Tktt_Type_spec"
598[clinic start generated code]*/
599/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b1ebf15c162ee229]*/
600
Guido van Rossum18468821994-06-20 07:49:28 +0000601/**** Tkapp Object ****/
602
603#ifndef WITH_APPINIT
604int
Fred Drake509d79a2000-07-08 04:04:38 +0000605Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000606{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000608
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 if (Tcl_Init(interp) == TCL_ERROR) {
610 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
611 return TCL_ERROR;
612 }
Guilherme Polob681df42009-02-09 22:33:59 +0000613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 _tkinter_skip_tk_init = Tcl_GetVar(interp,
615 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
616 if (_tkinter_skip_tk_init != NULL &&
617 strcmp(_tkinter_skip_tk_init, "1") == 0) {
618 return TCL_OK;
619 }
Guilherme Polob681df42009-02-09 22:33:59 +0000620
621#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000622 if (tk_load_failed) {
623 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
624 return TCL_ERROR;
625 }
Guilherme Polob681df42009-02-09 22:33:59 +0000626#endif
627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000628 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000629#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000631#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
633 return TCL_ERROR;
634 }
Guilherme Polob681df42009-02-09 22:33:59 +0000635
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000637}
638#endif /* !WITH_APPINIT */
639
Guido van Rossum18468821994-06-20 07:49:28 +0000640
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641
Barry Warsawfa701a81997-01-16 00:15:11 +0000642
643/* Initialize the Tk application; see the `main' function in
644 * `tkMain.c'.
645 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000646
Thomas Wouters58d05102000-07-24 14:43:35 +0000647static void EnableEventHook(void); /* Forward */
648static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000649
Barry Warsawfa701a81997-01-16 00:15:11 +0000650static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300651Tkapp_New(const char *screenName, const char *className,
652 int interactive, int wantobjects, int wantTk, int sync,
653 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000654{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000655 TkappObject *v;
656 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000657
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300658 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000659 if (v == NULL)
660 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000661
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 v->interp = Tcl_CreateInterp();
663 v->wantobjects = wantobjects;
664 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
665 TCL_GLOBAL_ONLY) != NULL;
666 v->thread_id = Tcl_GetCurrentThread();
667 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000668
669#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000670 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300671 PyErr_SetString(PyExc_RuntimeError,
672 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000673 Py_DECREF(v);
674 return 0;
675 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000676#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 if (v->threaded && tcl_lock) {
678 /* If Tcl is threaded, we don't need the lock. */
679 PyThread_free_lock(tcl_lock);
680 tcl_lock = NULL;
681 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000682
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200683 v->OldBooleanType = Tcl_GetObjType("boolean");
684 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 v->ByteArrayType = Tcl_GetObjType("bytearray");
686 v->DoubleType = Tcl_GetObjType("double");
687 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300688 v->WideIntType = Tcl_GetObjType("wideInt");
689 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 v->ListType = Tcl_GetObjType("list");
691 v->ProcBodyType = Tcl_GetObjType("procbody");
692 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 /* Delete the 'exit' command, which can screw things up */
695 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000696
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000697 if (screenName != NULL)
698 Tcl_SetVar2(v->interp, "env", "DISPLAY",
699 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000700
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 if (interactive)
702 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
703 else
704 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000705
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200707 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000708 if (!argv0) {
709 PyErr_NoMemory();
710 Py_DECREF(v);
711 return NULL;
712 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000713
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000714 strcpy(argv0, className);
Jordon Xu2ec70102019-09-11 00:04:08 +0800715 if (Py_ISUPPER(argv0[0]))
716 argv0[0] = Py_TOLOWER(argv0[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200718 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000719
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 if (! wantTk) {
721 Tcl_SetVar(v->interp,
722 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
723 }
Guilherme Polob681df42009-02-09 22:33:59 +0000724#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000725 else if (tk_load_failed) {
726 Tcl_SetVar(v->interp,
727 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
728 }
Guilherme Polob681df42009-02-09 22:33:59 +0000729#endif
David Aschere2b4b322004-02-18 05:59:53 +0000730
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000731 /* some initial arguments need to be in argv */
732 if (sync || use) {
733 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200734 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000735
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000736 if (sync)
737 len += sizeof "-sync";
738 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200739 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000740
Victor Stinneree6c3c72014-09-11 17:50:21 +0200741 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 if (!args) {
743 PyErr_NoMemory();
744 Py_DECREF(v);
745 return NULL;
746 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000747
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000748 args[0] = '\0';
749 if (sync)
750 strcat(args, "-sync");
751 if (use) {
752 if (sync)
753 strcat(args, " ");
754 strcat(args, "-use ");
755 strcat(args, use);
756 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000757
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000758 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200759 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000760 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000761
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500762#ifdef MS_WINDOWS
763 {
764 PyObject *str_path;
765 PyObject *utf8_path;
766 DWORD ret;
767
768 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
769 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
770 str_path = _get_tcl_lib_path();
771 if (str_path == NULL && PyErr_Occurred()) {
772 return NULL;
773 }
774 if (str_path != NULL) {
775 utf8_path = PyUnicode_AsUTF8String(str_path);
776 if (utf8_path == NULL) {
777 return NULL;
778 }
779 Tcl_SetVar(v->interp,
780 "tcl_library",
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300781 PyBytes_AS_STRING(utf8_path),
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500782 TCL_GLOBAL_ONLY);
783 Py_DECREF(utf8_path);
784 }
785 }
786 }
787#endif
788
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000789 if (Tcl_AppInit(v->interp) != TCL_OK) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300790 PyObject *result = Tkinter_Error(v);
Guilherme Polob681df42009-02-09 22:33:59 +0000791#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000792 if (wantTk) {
793 const char *_tkinter_tk_failed;
794 _tkinter_tk_failed = Tcl_GetVar(v->interp,
795 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000796
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000797 if ( _tkinter_tk_failed != NULL &&
798 strcmp(_tkinter_tk_failed, "1") == 0) {
799 tk_load_failed = 1;
800 }
801 }
Guilherme Polob681df42009-02-09 22:33:59 +0000802#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000803 Py_DECREF((PyObject *)v);
804 return (TkappObject *)result;
805 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000806
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000807 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000808
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000809 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000810}
811
Barry Warsawfa701a81997-01-16 00:15:11 +0000812
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000813static void
814Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000815 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000816{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000817 Py_BEGIN_ALLOW_THREADS;
818 Tcl_MutexLock(mutex);
819 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
820 Tcl_ThreadAlert(self->thread_id);
821 Tcl_ConditionWait(cond, mutex, NULL);
822 Tcl_MutexUnlock(mutex);
823 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000824}
825
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000826
Guido van Rossum18468821994-06-20 07:49:28 +0000827/** Tcl Eval **/
828
Martin v. Löwisffad6332002-11-26 09:28:05 +0000829typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000830 PyObject_HEAD
831 Tcl_Obj *value;
832 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000833} PyTclObject;
834
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300835static PyObject *PyTclObject_Type;
Victor Stinnerdaa97562020-02-07 03:37:06 +0100836#define PyTclObject_Check(v) (Py_TYPE(v) == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000837
838static PyObject *
839newPyTclObject(Tcl_Obj *arg)
840{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000841 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300842 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000843 if (self == NULL)
844 return NULL;
845 Tcl_IncrRefCount(arg);
846 self->value = arg;
847 self->string = NULL;
848 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000849}
850
851static void
852PyTclObject_dealloc(PyTclObject *self)
853{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200854 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000855 Tcl_DecrRefCount(self->value);
856 Py_XDECREF(self->string);
857 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200858 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000859}
860
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000861/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000862PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000863"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000864
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000865static PyObject *
866PyTclObject_string(PyTclObject *self, void *ignored)
867{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000868 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200869 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000870 if (!self->string)
871 return NULL;
872 }
873 Py_INCREF(self->string);
874 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000875}
876
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000877static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200878PyTclObject_str(PyTclObject *self)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000879{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200880 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 Py_INCREF(self->string);
882 return self->string;
883 }
884 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200885 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000886}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000887
Martin v. Löwisffad6332002-11-26 09:28:05 +0000888static PyObject *
889PyTclObject_repr(PyTclObject *self)
890{
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200891 PyObject *repr, *str = PyTclObject_str(self);
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300892 if (str == NULL)
893 return NULL;
894 repr = PyUnicode_FromFormat("<%s object: %R>",
895 self->value->typePtr->name, str);
896 Py_DECREF(str);
897 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000898}
899
Mark Dickinson211c6252009-02-01 10:28:51 +0000900static PyObject *
901PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000902{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000903 int result;
Mark Dickinson211c6252009-02-01 10:28:51 +0000904
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000905 /* neither argument should be NULL, unless something's gone wrong */
906 if (self == NULL || other == NULL) {
907 PyErr_BadInternalCall();
908 return NULL;
909 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000910
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000911 /* both arguments should be instances of PyTclObject */
912 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
stratakise8b19652017-11-02 11:32:54 +0100913 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000914 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000915
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000916 if (self == other)
917 /* fast path when self and other are identical */
918 result = 0;
919 else
920 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
921 Tcl_GetString(((PyTclObject *)other)->value));
stratakise8b19652017-11-02 11:32:54 +0100922 Py_RETURN_RICHCOMPARE(result, 0, op);
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000923}
924
Martin v. Löwis39195712003-01-04 00:33:13 +0000925PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
926
Martin v. Löwisffad6332002-11-26 09:28:05 +0000927static PyObject*
928get_typename(PyTclObject* obj, void* ignored)
929{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200930 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000931}
932
Martin v. Löwis39195712003-01-04 00:33:13 +0000933
Martin v. Löwisffad6332002-11-26 09:28:05 +0000934static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000935 {"typename", (getter)get_typename, NULL, get_typename__doc__},
936 {"string", (getter)PyTclObject_string, NULL,
937 PyTclObject_string__doc__},
938 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000939};
940
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300941static PyType_Slot PyTclObject_Type_slots[] = {
942 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
943 {Py_tp_repr, (reprfunc)PyTclObject_repr},
944 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200945 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300946 {Py_tp_richcompare, PyTclObject_richcompare},
947 {Py_tp_getset, PyTclObject_getsetlist},
948 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000949};
950
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300951static PyType_Spec PyTclObject_Type_spec = {
952 "_tkinter.Tcl_Obj",
953 sizeof(PyTclObject),
954 0,
955 Py_TPFLAGS_DEFAULT,
956 PyTclObject_Type_slots,
957};
958
959
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700960#if SIZE_MAX > INT_MAX
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300961#define CHECK_STRING_LENGTH(s) do { \
962 if (s != NULL && strlen(s) >= INT_MAX) { \
963 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
964 return NULL; \
965 } } while(0)
966#else
967#define CHECK_STRING_LENGTH(s)
968#endif
969
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300970#ifdef HAVE_LIBTOMMAMTH
971static Tcl_Obj*
972asBignumObj(PyObject *value)
973{
974 Tcl_Obj *result;
975 int neg;
976 PyObject *hexstr;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200977 const char *hexchars;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300978 mp_int bigValue;
979
980 neg = Py_SIZE(value) < 0;
981 hexstr = _PyLong_Format(value, 16);
982 if (hexstr == NULL)
983 return NULL;
984 hexchars = PyUnicode_AsUTF8(hexstr);
985 if (hexchars == NULL) {
986 Py_DECREF(hexstr);
987 return NULL;
988 }
989 hexchars += neg + 2; /* skip sign and "0x" */
990 mp_init(&bigValue);
991 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
992 mp_clear(&bigValue);
993 Py_DECREF(hexstr);
994 PyErr_NoMemory();
995 return NULL;
996 }
997 Py_DECREF(hexstr);
998 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
999 result = Tcl_NewBignumObj(&bigValue);
1000 mp_clear(&bigValue);
1001 if (result == NULL) {
1002 PyErr_NoMemory();
1003 return NULL;
1004 }
1005 return result;
1006}
1007#endif
1008
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001009static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001010AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001011{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001012 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001013
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001014 if (PyBytes_Check(value)) {
1015 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
1016 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1017 return NULL;
1018 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +03001019 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001020 (int)PyBytes_GET_SIZE(value));
1021 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001022
1023 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001024 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001025
1026 if (PyLong_CheckExact(value)) {
1027 int overflow;
1028 long longValue;
1029#ifdef TCL_WIDE_INT_TYPE
1030 Tcl_WideInt wideValue;
1031#endif
1032 longValue = PyLong_AsLongAndOverflow(value, &overflow);
1033 if (!overflow) {
1034 return Tcl_NewLongObj(longValue);
1035 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001036 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001037 fall through to wideInt handling. */
1038#ifdef TCL_WIDE_INT_TYPE
1039 if (_PyLong_AsByteArray((PyLongObject *)value,
1040 (unsigned char *)(void *)&wideValue,
1041 sizeof(wideValue),
1042 PY_LITTLE_ENDIAN,
1043 /* signed */ 1) == 0) {
1044 return Tcl_NewWideIntObj(wideValue);
1045 }
1046 PyErr_Clear();
1047#endif
1048 /* If there is an overflow in the wideInt conversion,
1049 fall through to bignum handling. */
1050#ifdef HAVE_LIBTOMMAMTH
1051 return asBignumObj(value);
1052#endif
1053 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001054 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001056
1057 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001058 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001059
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +03001060 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001061 Tcl_Obj **argv;
1062 Py_ssize_t size, i;
1063
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001064 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001065 if (size == 0)
1066 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001067 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001068 PyErr_SetString(PyExc_OverflowError,
1069 PyTuple_Check(value) ? "tuple is too long" :
1070 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001071 return NULL;
1072 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001073 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
1074 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001075 PyErr_NoMemory();
1076 return NULL;
1077 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001078 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001079 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001080 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001081 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001082 return result;
1083 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001084
1085 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001086 if (PyUnicode_READY(value) == -1)
1087 return NULL;
1088
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001089 Py_ssize_t size = PyUnicode_GET_LENGTH(value);
1090 if (size == 0) {
1091 return Tcl_NewStringObj("", 0);
1092 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001093 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1094 PyErr_SetString(PyExc_OverflowError, "string is too long");
1095 return NULL;
1096 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001097 if (PyUnicode_IS_ASCII(value)) {
1098 return Tcl_NewStringObj((const char *)PyUnicode_DATA(value),
1099 (int)size);
1100 }
1101
1102 PyObject *encoded;
1103#if USE_TCL_UNICODE
1104 if (sizeof(Tcl_UniChar) == 2)
1105 encoded = _PyUnicode_EncodeUTF16(value,
1106 "surrogatepass", NATIVE_BYTEORDER);
1107 else if (sizeof(Tcl_UniChar) == 4)
1108 encoded = _PyUnicode_EncodeUTF32(value,
1109 "surrogatepass", NATIVE_BYTEORDER);
1110 else
1111 Py_UNREACHABLE();
1112#else
1113 encoded = _PyUnicode_AsUTF8String(value, "surrogateescape");
1114#endif
1115 if (!encoded) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001116 return NULL;
1117 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001118 size = PyBytes_GET_SIZE(encoded);
1119 if (size > INT_MAX) {
1120 Py_DECREF(encoded);
1121 PyErr_SetString(PyExc_OverflowError, "string is too long");
1122 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001123 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001124#if USE_TCL_UNICODE
1125 result = Tcl_NewUnicodeObj((const Tcl_UniChar *)PyBytes_AS_STRING(encoded),
1126 (int)(size / sizeof(Tcl_UniChar)));
1127#else
1128 result = Tcl_NewStringObj(PyBytes_AS_STRING(encoded), (int)size);
1129#endif
1130 Py_DECREF(encoded);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001131 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001132 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001133
1134 if (PyTclObject_Check(value)) {
Serhiy Storchakadf13df42018-10-23 22:40:54 +03001135 return ((PyTclObject*)value)->value;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001136 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001137
1138 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001139 PyObject *v = PyObject_Str(value);
1140 if (!v)
1141 return 0;
1142 result = AsObj(v);
1143 Py_DECREF(v);
1144 return result;
1145 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001146}
1147
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001148static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001149fromBoolean(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001150{
1151 int boolValue;
1152 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1153 return Tkinter_Error(tkapp);
1154 return PyBool_FromLong(boolValue);
1155}
1156
Martin v. Löwisffad6332002-11-26 09:28:05 +00001157static PyObject*
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001158fromWideIntObj(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001159{
1160 Tcl_WideInt wideValue;
1161 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001162 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1163 return PyLong_FromLongLong(wideValue);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001164 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1165 sizeof(wideValue),
1166 PY_LITTLE_ENDIAN,
1167 /* signed */ 1);
1168 }
1169 return NULL;
1170}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001171
1172#ifdef HAVE_LIBTOMMAMTH
1173static PyObject*
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001174fromBignumObj(TkappObject *tkapp, Tcl_Obj *value)
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001175{
1176 mp_int bigValue;
1177 unsigned long numBytes;
1178 unsigned char *bytes;
1179 PyObject *res;
1180
1181 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1182 return Tkinter_Error(tkapp);
1183 numBytes = mp_unsigned_bin_size(&bigValue);
1184 bytes = PyMem_Malloc(numBytes);
1185 if (bytes == NULL) {
1186 mp_clear(&bigValue);
1187 return PyErr_NoMemory();
1188 }
1189 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1190 &numBytes) != MP_OKAY) {
1191 mp_clear(&bigValue);
1192 PyMem_Free(bytes);
1193 return PyErr_NoMemory();
1194 }
1195 res = _PyLong_FromByteArray(bytes, numBytes,
1196 /* big-endian */ 0,
1197 /* unsigned */ 0);
1198 PyMem_Free(bytes);
1199 if (res != NULL && bigValue.sign == MP_NEG) {
1200 PyObject *res2 = PyNumber_Negative(res);
1201 Py_DECREF(res);
1202 res = res2;
1203 }
1204 mp_clear(&bigValue);
1205 return res;
1206}
1207#endif
1208
Martin v. Löwisffad6332002-11-26 09:28:05 +00001209static PyObject*
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001210FromObj(TkappObject *tkapp, Tcl_Obj *value)
Martin v. Löwisffad6332002-11-26 09:28:05 +00001211{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001212 PyObject *result = NULL;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001213 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001214
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001215 if (value->typePtr == NULL) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001216 return unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001217 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001218
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001219 if (value->typePtr == tkapp->BooleanType ||
1220 value->typePtr == tkapp->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001221 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001222 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001223
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001224 if (value->typePtr == tkapp->ByteArrayType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001225 int size;
1226 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1227 return PyBytes_FromStringAndSize(data, size);
1228 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001229
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001230 if (value->typePtr == tkapp->DoubleType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001231 return PyFloat_FromDouble(value->internalRep.doubleValue);
1232 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001233
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001234 if (value->typePtr == tkapp->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001235 long longValue;
1236 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1237 return PyLong_FromLong(longValue);
1238 /* If there is an error in the long conversion,
1239 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001240 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001241
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001242 if (value->typePtr == tkapp->IntType ||
1243 value->typePtr == tkapp->WideIntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001244 result = fromWideIntObj(tkapp, value);
1245 if (result != NULL || PyErr_Occurred())
1246 return result;
1247 Tcl_ResetResult(interp);
1248 /* If there is an error in the wideInt conversion,
1249 fall through to bignum handling. */
1250 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001251
1252#ifdef HAVE_LIBTOMMAMTH
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001253 if (value->typePtr == tkapp->IntType ||
1254 value->typePtr == tkapp->WideIntType ||
1255 value->typePtr == tkapp->BignumType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001256 return fromBignumObj(tkapp, value);
1257 }
1258#endif
1259
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001260 if (value->typePtr == tkapp->ListType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001261 int size;
1262 int i, status;
1263 PyObject *elem;
1264 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001265
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001266 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001267 if (status == TCL_ERROR)
1268 return Tkinter_Error(tkapp);
1269 result = PyTuple_New(size);
1270 if (!result)
1271 return NULL;
1272 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001273 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001274 if (status == TCL_ERROR) {
1275 Py_DECREF(result);
1276 return Tkinter_Error(tkapp);
1277 }
1278 elem = FromObj(tkapp, tcl_elem);
1279 if (!elem) {
1280 Py_DECREF(result);
1281 return NULL;
1282 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001283 PyTuple_SET_ITEM(result, i, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 }
1285 return result;
1286 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001287
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001288 if (value->typePtr == tkapp->ProcBodyType) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001289 /* fall through: return tcl object. */
1290 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001291
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001292 if (value->typePtr == tkapp->StringType) {
1293 return unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001294 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001295
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001296#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001297 if (tkapp->BooleanType == NULL &&
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001298 strcmp(value->typePtr->name, "booleanString") == 0) {
1299 /* booleanString type is not registered in Tcl */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001300 tkapp->BooleanType = value->typePtr;
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001301 return fromBoolean(tkapp, value);
1302 }
1303#endif
1304
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001305#ifdef HAVE_LIBTOMMAMTH
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001306 if (tkapp->BignumType == NULL &&
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001307 strcmp(value->typePtr->name, "bignum") == 0) {
1308 /* bignum type is not registered in Tcl */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001309 tkapp->BignumType = value->typePtr;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001310 return fromBignumObj(tkapp, value);
1311 }
1312#endif
1313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001314 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001315}
1316
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001317/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001318TCL_DECLARE_MUTEX(call_mutex)
1319
1320typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001321 Tcl_Event ev; /* Must be first */
1322 TkappObject *self;
1323 PyObject *args;
1324 int flags;
1325 PyObject **res;
1326 PyObject **exc_type, **exc_value, **exc_tb;
1327 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001328} Tkapp_CallEvent;
1329
1330void
1331Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001332{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001333 int i;
1334 for (i = 0; i < objc; i++)
1335 Tcl_DecrRefCount(objv[i]);
1336 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001337 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001338}
Guido van Rossum18468821994-06-20 07:49:28 +00001339
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001340/* Convert Python objects to Tcl objects. This must happen in the
1341 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001342
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001343static Tcl_Obj**
1344Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1345{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001347 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001348 if (args == NULL)
1349 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001350
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001351 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 objv[0] = AsObj(args);
Serhiy Storchaka0b3ec192017-03-23 17:53:47 +02001353 if (objv[0] == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001354 goto finally;
1355 objc = 1;
1356 Tcl_IncrRefCount(objv[0]);
1357 }
1358 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001359 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001361 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001362 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001363 PyErr_SetString(PyExc_OverflowError,
1364 PyTuple_Check(args) ? "tuple is too long" :
1365 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001366 return NULL;
1367 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001368 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001369 if (objv == NULL) {
1370 PyErr_NoMemory();
1371 objc = 0;
1372 goto finally;
1373 }
1374 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001376 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001377 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001378 if (v == Py_None) {
1379 objc = i;
1380 break;
1381 }
1382 objv[i] = AsObj(v);
1383 if (!objv[i]) {
1384 /* Reset objc, so it attempts to clear
1385 objects only up to i. */
1386 objc = i;
1387 goto finally;
1388 }
1389 Tcl_IncrRefCount(objv[i]);
1390 }
1391 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001392 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001393 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001394finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001395 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001396 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001397}
Guido van Rossum212643f1998-04-29 16:22:14 +00001398
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001399/* Convert the results of a command call into a Python string. */
1400
1401static PyObject *
1402Tkapp_UnicodeResult(TkappObject *self)
1403{
1404 return unicodeFromTclObj(Tcl_GetObjResult(self->interp));
1405}
1406
1407
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001408/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001409
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001410static PyObject *
1411Tkapp_ObjectResult(TkappObject *self)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001412{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001413 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001414 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001415 if (self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001416 /* Not sure whether the IncrRef is necessary, but something
1417 may overwrite the interpreter result while we are
1418 converting it. */
1419 Tcl_IncrRefCount(value);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001420 res = FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001421 Tcl_DecrRefCount(value);
1422 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001423 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001424 }
1425 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001426}
Guido van Rossum632de272000-03-29 00:19:50 +00001427
Benjamin Peterson5879d412009-03-30 14:51:56 +00001428
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001429/* Tkapp_CallProc is the event procedure that is executed in the context of
1430 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1431 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001432
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001433static int
1434Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1435{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001436 Tcl_Obj *objStore[ARGSZ];
1437 Tcl_Obj **objv;
1438 int objc;
1439 int i;
1440 ENTER_PYTHON
1441 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1442 if (!objv) {
1443 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1444 *(e->res) = NULL;
1445 }
1446 LEAVE_PYTHON
1447 if (!objv)
1448 goto done;
1449 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1450 ENTER_PYTHON
1451 if (i == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001452 *(e->res) = Tkinter_Error(e->self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001453 }
1454 else {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001455 *(e->res) = Tkapp_ObjectResult(e->self);
1456 }
1457 if (*(e->res) == NULL) {
1458 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001459 }
1460 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001462 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001463done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001464 /* Wake up calling thread. */
1465 Tcl_MutexLock(&call_mutex);
1466 Tcl_ConditionNotify(e->done);
1467 Tcl_MutexUnlock(&call_mutex);
1468 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001469}
1470
Benjamin Peterson5879d412009-03-30 14:51:56 +00001471
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001472/* This is the main entry point for calling a Tcl command.
1473 It supports three cases, with regard to threading:
1474 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1475 the context of the calling thread.
1476 2. Tcl is threaded, caller of the command is in the interpreter thread:
1477 Execute the command in the calling thread. Since the Tcl lock will
1478 not be used, we can merge that with case 1.
1479 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1480 the interpreter thread. Allocation of Tcl objects needs to occur in the
1481 interpreter thread, so we ship the PyObject* args to the target thread,
1482 and perform processing there. */
1483
1484static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001485Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001487 Tcl_Obj *objStore[ARGSZ];
1488 Tcl_Obj **objv = NULL;
1489 int objc, i;
1490 PyObject *res = NULL;
1491 TkappObject *self = (TkappObject*)selfptr;
1492 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001494 /* If args is a single tuple, replace with contents of tuple */
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001495 if (PyTuple_GET_SIZE(args) == 1) {
1496 PyObject *item = PyTuple_GET_ITEM(args, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001497 if (PyTuple_Check(item))
1498 args = item;
1499 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001500 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1501 /* We cannot call the command directly. Instead, we must
1502 marshal the parameters to the interpreter thread. */
1503 Tkapp_CallEvent *ev;
1504 Tcl_Condition cond = NULL;
1505 PyObject *exc_type, *exc_value, *exc_tb;
1506 if (!WaitForMainloop(self))
1507 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001508 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1509 if (ev == NULL) {
1510 PyErr_NoMemory();
1511 return NULL;
1512 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001513 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1514 ev->self = self;
1515 ev->args = args;
1516 ev->res = &res;
1517 ev->exc_type = &exc_type;
1518 ev->exc_value = &exc_value;
1519 ev->exc_tb = &exc_tb;
1520 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001521
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001522 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001524 if (res == NULL) {
1525 if (exc_type)
1526 PyErr_Restore(exc_type, exc_value, exc_tb);
1527 else
1528 PyErr_SetObject(Tkinter_TclError, exc_value);
1529 }
1530 Tcl_ConditionFinalize(&cond);
1531 }
1532 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001534
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001535 objv = Tkapp_CallArgs(args, objStore, &objc);
1536 if (!objv)
1537 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001539 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001542
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001543 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001544
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001545 if (i == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001546 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001548 res = Tkapp_ObjectResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001549
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001551
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001552 Tkapp_CallDeallocArgs(objv, objStore, objc);
1553 }
1554 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001555}
1556
1557
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001558/*[clinic input]
1559_tkinter.tkapp.eval
1560
1561 script: str
1562 /
1563
1564[clinic start generated code]*/
1565
Barry Warsawfa701a81997-01-16 00:15:11 +00001566static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001567_tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1568/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001569{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001570 PyObject *res = NULL;
1571 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001572
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001573 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001574 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001576 ENTER_TCL
1577 err = Tcl_Eval(Tkapp_Interp(self), script);
1578 ENTER_OVERLAP
1579 if (err == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001580 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001581 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001582 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001583 LEAVE_OVERLAP_TCL
1584 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001585}
1586
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001587/*[clinic input]
1588_tkinter.tkapp.evalfile
1589
1590 fileName: str
1591 /
1592
1593[clinic start generated code]*/
1594
Guido van Rossum18468821994-06-20 07:49:28 +00001595static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001596_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1597/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001598{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001599 PyObject *res = NULL;
1600 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001601
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001602 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001603 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001605 ENTER_TCL
1606 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1607 ENTER_OVERLAP
1608 if (err == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001609 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001610 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001611 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001612 LEAVE_OVERLAP_TCL
1613 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001614}
1615
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001616/*[clinic input]
1617_tkinter.tkapp.record
1618
1619 script: str
1620 /
1621
1622[clinic start generated code]*/
1623
Guido van Rossum18468821994-06-20 07:49:28 +00001624static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001625_tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1626/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001627{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001628 PyObject *res = NULL;
1629 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001630
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001631 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001632 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001634 ENTER_TCL
1635 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1636 ENTER_OVERLAP
1637 if (err == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001638 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001639 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001640 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001641 LEAVE_OVERLAP_TCL
1642 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001643}
1644
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001645/*[clinic input]
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001646_tkinter.tkapp.adderrorinfo
Guido van Rossum18468821994-06-20 07:49:28 +00001647
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001648 msg: str
1649 /
1650
1651[clinic start generated code]*/
1652
1653static PyObject *
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001654_tkinter_tkapp_adderrorinfo_impl(TkappObject *self, const char *msg)
1655/*[clinic end generated code: output=52162eaca2ee53cb input=f4b37aec7c7e8c77]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001656{
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001657 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001658 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001659
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001660 ENTER_TCL
1661 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1662 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001663
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001664 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001665}
1666
Barry Warsawfa701a81997-01-16 00:15:11 +00001667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001668
Guido van Rossum18468821994-06-20 07:49:28 +00001669/** Tcl Variable **/
1670
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001671typedef PyObject* (*EventFunc)(TkappObject *, PyObject *, int);
Benjamin Peterson5879d412009-03-30 14:51:56 +00001672
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001673TCL_DECLARE_MUTEX(var_mutex)
1674
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001675typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001676 Tcl_Event ev; /* must be first */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001677 TkappObject *self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001678 PyObject *args;
1679 int flags;
1680 EventFunc func;
1681 PyObject **res;
1682 PyObject **exc_type;
1683 PyObject **exc_val;
1684 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001685} VarEvent;
1686
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001687/*[python]
1688
1689class varname_converter(CConverter):
1690 type = 'const char *'
1691 converter = 'varname_converter'
1692
1693[python]*/
1694/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1695
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001696static int
1697varname_converter(PyObject *in, void *_out)
1698{
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +02001699 const char *s;
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001700 const char **out = (const char**)_out;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001701 if (PyBytes_Check(in)) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001702 if (PyBytes_GET_SIZE(in) > INT_MAX) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001703 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1704 return 0;
1705 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001706 s = PyBytes_AS_STRING(in);
1707 if (strlen(s) != (size_t)PyBytes_GET_SIZE(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001708 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001709 return 0;
1710 }
1711 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001712 return 1;
1713 }
1714 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001715 Py_ssize_t size;
1716 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001717 if (s == NULL) {
1718 return 0;
1719 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001720 if (size > INT_MAX) {
1721 PyErr_SetString(PyExc_OverflowError, "string is too long");
1722 return 0;
1723 }
Victor Stinner706768c2014-08-16 01:03:39 +02001724 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001725 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001726 return 0;
1727 }
1728 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001729 return 1;
1730 }
1731 if (PyTclObject_Check(in)) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001732 *out = Tcl_GetString(((PyTclObject *)in)->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001733 return 1;
1734 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001735 PyErr_Format(PyExc_TypeError,
1736 "must be str, bytes or Tcl_Obj, not %.50s",
Victor Stinnerdaa97562020-02-07 03:37:06 +01001737 Py_TYPE(in)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001739}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001740
Benjamin Peterson5879d412009-03-30 14:51:56 +00001741
Martin v. Löwis59683e82008-06-13 07:50:45 +00001742static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001743var_perform(VarEvent *ev)
1744{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001745 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1746 if (!*(ev->res)) {
1747 PyObject *exc, *val, *tb;
1748 PyErr_Fetch(&exc, &val, &tb);
1749 PyErr_NormalizeException(&exc, &val, &tb);
1750 *(ev->exc_type) = exc;
1751 *(ev->exc_val) = val;
Serhiy Storchaka3ec5f422016-10-28 12:14:34 +03001752 Py_XDECREF(tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001753 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001754
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001755}
1756
1757static int
1758var_proc(VarEvent* ev, int flags)
1759{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001760 ENTER_PYTHON
1761 var_perform(ev);
1762 Tcl_MutexLock(&var_mutex);
1763 Tcl_ConditionNotify(ev->cond);
1764 Tcl_MutexUnlock(&var_mutex);
1765 LEAVE_PYTHON
1766 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001767}
1768
Benjamin Peterson5879d412009-03-30 14:51:56 +00001769
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001770static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001771var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001772{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001773 TkappObject *self = (TkappObject*)selfptr;
1774 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 VarEvent *ev;
1776 PyObject *res, *exc_type, *exc_val;
1777 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001778
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001779 /* The current thread is not the interpreter thread. Marshal
1780 the call to the interpreter thread, then wait for
1781 completion. */
1782 if (!WaitForMainloop(self))
1783 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001784
Serhiy Storchaka07940882014-09-11 10:38:54 +03001785 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1786 if (ev == NULL) {
1787 PyErr_NoMemory();
1788 return NULL;
1789 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001790 ev->self = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001791 ev->args = args;
1792 ev->flags = flags;
1793 ev->func = func;
1794 ev->res = &res;
1795 ev->exc_type = &exc_type;
1796 ev->exc_val = &exc_val;
1797 ev->cond = &cond;
1798 ev->ev.proc = (Tcl_EventProc*)var_proc;
1799 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1800 Tcl_ConditionFinalize(&cond);
1801 if (!res) {
1802 PyErr_SetObject(exc_type, exc_val);
1803 Py_DECREF(exc_type);
1804 Py_DECREF(exc_val);
1805 return NULL;
1806 }
1807 return res;
1808 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001809 /* Tcl is not threaded, or this is the interpreter thread. */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001810 return func(self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001811}
1812
Guido van Rossum18468821994-06-20 07:49:28 +00001813static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001814SetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001815{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001816 const char *name1, *name2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001817 PyObject *newValue;
1818 PyObject *res = NULL;
1819 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001820
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001821 switch (PyTuple_GET_SIZE(args)) {
1822 case 2:
1823 if (!PyArg_ParseTuple(args, "O&O:setvar",
1824 varname_converter, &name1, &newValue))
1825 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001826 /* XXX Acquire tcl lock??? */
1827 newval = AsObj(newValue);
1828 if (newval == NULL)
1829 return NULL;
1830 ENTER_TCL
1831 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1832 newval, flags);
1833 ENTER_OVERLAP
1834 if (!ok)
1835 Tkinter_Error(self);
1836 else {
1837 res = Py_None;
1838 Py_INCREF(res);
1839 }
1840 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001841 break;
1842 case 3:
1843 if (!PyArg_ParseTuple(args, "ssO:setvar",
1844 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001845 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001846 CHECK_STRING_LENGTH(name1);
1847 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001848 /* XXX must hold tcl lock already??? */
1849 newval = AsObj(newValue);
1850 ENTER_TCL
1851 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1852 ENTER_OVERLAP
1853 if (!ok)
1854 Tkinter_Error(self);
1855 else {
1856 res = Py_None;
1857 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001858 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001859 LEAVE_OVERLAP_TCL
1860 break;
1861 default:
1862 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1863 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001864 }
1865 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001866}
1867
1868static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001869Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001870{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001871 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001872}
1873
1874static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001875Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001876{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001877 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001878}
1879
Barry Warsawfa701a81997-01-16 00:15:11 +00001880
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001881
Guido van Rossum18468821994-06-20 07:49:28 +00001882static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001883GetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001884{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001885 const char *name1, *name2=NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001886 PyObject *res = NULL;
1887 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001888
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001889 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1890 varname_converter, &name1, &name2))
1891 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001892
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001893 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001894 ENTER_TCL
1895 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1896 ENTER_OVERLAP
1897 if (tres == NULL) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001898 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001899 } else {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001900 if (self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001901 res = FromObj(self, tres);
1902 }
1903 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001904 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001905 }
1906 }
1907 LEAVE_OVERLAP_TCL
1908 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001909}
1910
1911static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001912Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001913{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001914 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001915}
1916
1917static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001918Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001919{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001920 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001921}
1922
Barry Warsawfa701a81997-01-16 00:15:11 +00001923
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001924
Guido van Rossum18468821994-06-20 07:49:28 +00001925static PyObject *
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001926UnsetVar(TkappObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001927{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001928 char *name1, *name2=NULL;
1929 int code;
1930 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001931
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001932 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1933 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001934
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001935 CHECK_STRING_LENGTH(name1);
1936 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001937 ENTER_TCL
1938 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1939 ENTER_OVERLAP
1940 if (code == TCL_ERROR)
1941 res = Tkinter_Error(self);
1942 else {
1943 Py_INCREF(Py_None);
1944 res = Py_None;
1945 }
1946 LEAVE_OVERLAP_TCL
1947 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001948}
1949
1950static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001951Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001952{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001953 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001954}
1955
1956static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001957Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001958{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001959 return var_invoke(UnsetVar, self, args,
1960 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001961}
1962
Barry Warsawfa701a81997-01-16 00:15:11 +00001963
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001964
Guido van Rossum18468821994-06-20 07:49:28 +00001965/** Tcl to Python **/
1966
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001967/*[clinic input]
1968_tkinter.tkapp.getint
1969
1970 arg: object
1971 /
1972
1973[clinic start generated code]*/
1974
Guido van Rossum18468821994-06-20 07:49:28 +00001975static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001976_tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
1977/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001978{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001979 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001980 Tcl_Obj *value;
1981 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00001982
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001983 if (PyLong_Check(arg)) {
1984 Py_INCREF(arg);
1985 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001986 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001987
Serhiy Storchaka645058d2015-05-06 14:00:04 +03001988 if (PyTclObject_Check(arg)) {
1989 value = ((PyTclObject*)arg)->value;
1990 Tcl_IncrRefCount(value);
1991 }
1992 else {
1993 if (!PyArg_Parse(arg, "s:getint", &s))
1994 return NULL;
1995 CHECK_STRING_LENGTH(s);
1996 value = Tcl_NewStringObj(s, -1);
1997 if (value == NULL)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03001998 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03001999 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002000 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
2001 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
2002
2003 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
2004 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
2005 */
2006#ifdef HAVE_LIBTOMMAMTH
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002007 result = fromBignumObj(self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002008#else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002009 result = fromWideIntObj(self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002010#endif
2011 Tcl_DecrRefCount(value);
2012 if (result != NULL || PyErr_Occurred())
2013 return result;
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002014 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00002015}
2016
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002017/*[clinic input]
2018_tkinter.tkapp.getdouble
2019
2020 arg: object
2021 /
2022
2023[clinic start generated code]*/
2024
Guido van Rossum18468821994-06-20 07:49:28 +00002025static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002026_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
2027/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002028{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002029 char *s;
2030 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00002031
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002032 if (PyFloat_Check(arg)) {
2033 Py_INCREF(arg);
2034 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002035 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002036
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002037 if (PyNumber_Check(arg)) {
2038 return PyNumber_Float(arg);
2039 }
2040
2041 if (PyTclObject_Check(arg)) {
2042 if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
2043 ((PyTclObject*)arg)->value,
2044 &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002045 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002046 return PyFloat_FromDouble(v);
2047 }
2048
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002049 if (!PyArg_Parse(arg, "s:getdouble", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002050 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002051 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002052 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002053 return Tkinter_Error(self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002054 return PyFloat_FromDouble(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002055}
2056
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002057/*[clinic input]
2058_tkinter.tkapp.getboolean
2059
2060 arg: object
2061 /
2062
2063[clinic start generated code]*/
2064
Guido van Rossum18468821994-06-20 07:49:28 +00002065static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002066_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
2067/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002068{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002069 char *s;
2070 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002071
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002072 if (PyLong_Check(arg)) { /* int or bool */
2073 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002074 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002075
2076 if (PyTclObject_Check(arg)) {
2077 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2078 ((PyTclObject*)arg)->value,
2079 &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002080 return Tkinter_Error(self);
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002081 return PyBool_FromLong(v);
2082 }
2083
2084 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002085 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002086 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002087 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002088 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002089 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002090}
2091
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002092/*[clinic input]
2093_tkinter.tkapp.exprstring
2094
2095 s: str
2096 /
2097
2098[clinic start generated code]*/
2099
Guido van Rossum18468821994-06-20 07:49:28 +00002100static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002101_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2102/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002103{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002104 PyObject *res = NULL;
2105 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002106
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002107 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002108 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002109
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002110 ENTER_TCL
2111 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2112 ENTER_OVERLAP
2113 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002114 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115 else
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002116 res = Tkapp_UnicodeResult(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002117 LEAVE_OVERLAP_TCL
2118 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002119}
2120
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002121/*[clinic input]
2122_tkinter.tkapp.exprlong
2123
2124 s: str
2125 /
2126
2127[clinic start generated code]*/
2128
Guido van Rossum18468821994-06-20 07:49:28 +00002129static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002130_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2131/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002132{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002133 PyObject *res = NULL;
2134 int retval;
2135 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002136
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002137 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002139
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002140 ENTER_TCL
2141 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2142 ENTER_OVERLAP
2143 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002144 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002145 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002146 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002147 LEAVE_OVERLAP_TCL
2148 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002149}
2150
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002151/*[clinic input]
2152_tkinter.tkapp.exprdouble
2153
2154 s: str
2155 /
2156
2157[clinic start generated code]*/
2158
Guido van Rossum18468821994-06-20 07:49:28 +00002159static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002160_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2161/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002162{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002163 PyObject *res = NULL;
2164 double v;
2165 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002166
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002167 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002168 CHECK_TCL_APPARTMENT;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002169 ENTER_TCL
2170 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2171 ENTER_OVERLAP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002172 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002173 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002174 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002175 res = PyFloat_FromDouble(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002176 LEAVE_OVERLAP_TCL
2177 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002178}
2179
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002180/*[clinic input]
2181_tkinter.tkapp.exprboolean
2182
2183 s: str
2184 /
2185
2186[clinic start generated code]*/
2187
Guido van Rossum18468821994-06-20 07:49:28 +00002188static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002189_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2190/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002191{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002192 PyObject *res = NULL;
2193 int retval;
2194 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002195
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002196 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 CHECK_TCL_APPARTMENT;
2198 ENTER_TCL
2199 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2200 ENTER_OVERLAP
2201 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002202 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002203 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002204 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002205 LEAVE_OVERLAP_TCL
2206 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002207}
2208
Barry Warsawfa701a81997-01-16 00:15:11 +00002209
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002210
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002211/*[clinic input]
2212_tkinter.tkapp.splitlist
2213
2214 arg: object
2215 /
2216
2217[clinic start generated code]*/
2218
Guido van Rossum18468821994-06-20 07:49:28 +00002219static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002220_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2221/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002222{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002223 char *list;
2224 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002225 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002226 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002227 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002228
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002229 if (PyTclObject_Check(arg)) {
2230 int objc;
2231 Tcl_Obj **objv;
2232 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2233 ((PyTclObject*)arg)->value,
2234 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002235 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002236 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002237 if (!(v = PyTuple_New(objc)))
2238 return NULL;
2239 for (i = 0; i < objc; i++) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002240 PyObject *s = FromObj(self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002241 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002242 Py_DECREF(v);
2243 return NULL;
2244 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002245 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002246 }
2247 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002248 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002249 if (PyTuple_Check(arg)) {
2250 Py_INCREF(arg);
2251 return arg;
2252 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002253 if (PyList_Check(arg)) {
2254 return PySequence_Tuple(arg);
2255 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002256
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002257 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002258 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002259
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002260 if (strlen(list) >= INT_MAX) {
2261 PyErr_SetString(PyExc_OverflowError, "string is too long");
2262 PyMem_Free(list);
2263 return NULL;
2264 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002265 if (Tcl_SplitList(Tkapp_Interp(self), list,
2266 &argc, &argv) == TCL_ERROR) {
2267 PyMem_Free(list);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002268 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002269 }
Guido van Rossum18468821994-06-20 07:49:28 +00002270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002271 if (!(v = PyTuple_New(argc)))
2272 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002273
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002274 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002275 PyObject *s = unicodeFromTclString(argv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002276 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002277 Py_DECREF(v);
2278 v = NULL;
2279 goto finally;
2280 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002281 PyTuple_SET_ITEM(v, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002282 }
Guido van Rossum18468821994-06-20 07:49:28 +00002283
Barry Warsawfa701a81997-01-16 00:15:11 +00002284 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002285 ckfree(FREECAST argv);
2286 PyMem_Free(list);
2287 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002288}
2289
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002290/*[clinic input]
2291_tkinter.tkapp.split
2292
2293 arg: object
2294 /
2295
2296[clinic start generated code]*/
2297
Guido van Rossum18468821994-06-20 07:49:28 +00002298static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002299_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2300/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002301{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002302 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002303 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002304
Serhiy Storchakad05b0002019-10-08 14:31:35 +03002305 if (PyErr_WarnEx(PyExc_DeprecationWarning,
2306 "split() is deprecated; consider using splitlist() instead", 1))
2307 {
2308 return NULL;
2309 }
2310
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002311 if (PyTclObject_Check(arg)) {
2312 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2313 int objc;
2314 Tcl_Obj **objv;
2315 int i;
2316 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2317 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002318 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002319 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002320 if (objc == 0)
2321 return PyUnicode_FromString("");
2322 if (objc == 1)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002323 return FromObj(self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002324 if (!(v = PyTuple_New(objc)))
2325 return NULL;
2326 for (i = 0; i < objc; i++) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002327 PyObject *s = FromObj(self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002328 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002329 Py_DECREF(v);
2330 return NULL;
2331 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002332 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002333 }
2334 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002335 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002336 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002337 return SplitObj(arg);
2338
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002339 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002340 return NULL;
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002341 if (strlen(list) >= INT_MAX) {
2342 PyErr_SetString(PyExc_OverflowError, "string is too long");
2343 PyMem_Free(list);
2344 return NULL;
2345 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002346 v = Split(list);
2347 PyMem_Free(list);
2348 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002349}
2350
Barry Warsawfa701a81997-01-16 00:15:11 +00002351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002352
Guido van Rossum18468821994-06-20 07:49:28 +00002353/** Tcl Command **/
2354
Guido van Rossum00d93061998-05-28 23:06:38 +00002355/* Client data struct */
2356typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002357 PyObject *self;
2358 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002359} PythonCmd_ClientData;
2360
2361static int
Fred Drake509d79a2000-07-08 04:04:38 +00002362PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002363{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002364 errorInCmd = 1;
2365 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2366 LEAVE_PYTHON
2367 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002368}
2369
Guido van Rossum18468821994-06-20 07:49:28 +00002370/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002371 * function or method.
2372 */
Guido van Rossum18468821994-06-20 07:49:28 +00002373static int
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002374PythonCmd(ClientData clientData, Tcl_Interp *interp,
2375 int objc, Tcl_Obj *const objv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002376{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002377 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002378 PyObject *args, *res;
2379 int i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002380 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002382 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002383
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002384 /* Create argument tuple (objv1, ..., objvN) */
2385 if (!(args = PyTuple_New(objc - 1)))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002386 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002387
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002388 for (i = 0; i < (objc - 1); i++) {
2389 PyObject *s = unicodeFromTclObj(objv[i + 1]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002390 if (!s) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002391 Py_DECREF(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002392 return PythonCmd_Error(interp);
2393 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002394 PyTuple_SET_ITEM(args, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002395 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002396
2397 res = PyObject_Call(data->func, args, NULL);
2398 Py_DECREF(args);
Guido van Rossum18468821994-06-20 07:49:28 +00002399
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002400 if (res == NULL)
2401 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002403 obj_res = AsObj(res);
2404 if (obj_res == NULL) {
2405 Py_DECREF(res);
2406 return PythonCmd_Error(interp);
2407 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002408 Tcl_SetObjResult(interp, obj_res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002409 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002411 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002412
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002413 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +00002414}
2415
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002416
Guido van Rossum18468821994-06-20 07:49:28 +00002417static void
Fred Drake509d79a2000-07-08 04:04:38 +00002418PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002419{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002420 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002421
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002422 ENTER_PYTHON
2423 Py_XDECREF(data->self);
2424 Py_XDECREF(data->func);
2425 PyMem_DEL(data);
2426 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002427}
2428
Barry Warsawfa701a81997-01-16 00:15:11 +00002429
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002430
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002431
2432TCL_DECLARE_MUTEX(command_mutex)
2433
2434typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002435 Tcl_Event ev;
2436 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002437 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002438 int create;
2439 int *status;
2440 ClientData *data;
2441 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002442} CommandEvent;
2443
2444static int
2445Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002446{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002447 if (ev->create)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002448 *ev->status = Tcl_CreateObjCommand(
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002449 ev->interp, ev->name, PythonCmd,
2450 ev->data, PythonCmdDelete) == NULL;
2451 else
2452 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2453 Tcl_MutexLock(&command_mutex);
2454 Tcl_ConditionNotify(ev->done);
2455 Tcl_MutexUnlock(&command_mutex);
2456 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002457}
2458
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002459/*[clinic input]
2460_tkinter.tkapp.createcommand
2461
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002462 name: str
2463 func: object
2464 /
2465
2466[clinic start generated code]*/
2467
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002468static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002469_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2470 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002471/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002472{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002473 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002474 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002475
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002476 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 if (!PyCallable_Check(func)) {
2478 PyErr_SetString(PyExc_TypeError, "command not callable");
2479 return NULL;
2480 }
Guido van Rossum18468821994-06-20 07:49:28 +00002481
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002482 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2483 !WaitForMainloop(self))
2484 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002486 data = PyMem_NEW(PythonCmd_ClientData, 1);
2487 if (!data)
2488 return PyErr_NoMemory();
2489 Py_INCREF(self);
2490 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002491 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002492 data->func = func;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002493 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2494 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002495 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2496 if (ev == NULL) {
2497 PyErr_NoMemory();
2498 PyMem_DEL(data);
2499 return NULL;
2500 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002501 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2502 ev->interp = self->interp;
2503 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002504 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002505 ev->data = (ClientData)data;
2506 ev->status = &err;
2507 ev->done = &cond;
2508 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2509 Tcl_ConditionFinalize(&cond);
2510 }
2511 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002512 {
2513 ENTER_TCL
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002514 err = Tcl_CreateObjCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002515 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002516 (ClientData)data, PythonCmdDelete) == NULL;
2517 LEAVE_TCL
2518 }
2519 if (err) {
2520 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2521 PyMem_DEL(data);
2522 return NULL;
2523 }
Guido van Rossum18468821994-06-20 07:49:28 +00002524
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002525 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002526}
2527
Barry Warsawfa701a81997-01-16 00:15:11 +00002528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002529
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002530/*[clinic input]
2531_tkinter.tkapp.deletecommand
2532
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002533 name: str
2534 /
2535
2536[clinic start generated code]*/
2537
Guido van Rossum18468821994-06-20 07:49:28 +00002538static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002539_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002540/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002541{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002542 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002543
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002544 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002546 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2547 Tcl_Condition cond = NULL;
2548 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002549 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2550 if (ev == NULL) {
2551 PyErr_NoMemory();
2552 return NULL;
2553 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002554 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2555 ev->interp = self->interp;
2556 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002557 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002558 ev->status = &err;
2559 ev->done = &cond;
2560 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2561 &command_mutex);
2562 Tcl_ConditionFinalize(&cond);
2563 }
2564 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002565 {
2566 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002567 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002568 LEAVE_TCL
2569 }
2570 if (err == -1) {
2571 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2572 return NULL;
2573 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002574 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002575}
2576
Barry Warsawfa701a81997-01-16 00:15:11 +00002577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002578
Guido van Rossum00d93061998-05-28 23:06:38 +00002579#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002580/** File Handler **/
2581
Guido van Rossum00d93061998-05-28 23:06:38 +00002582typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002583 PyObject *func;
2584 PyObject *file;
2585 int id;
2586 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002587} FileHandler_ClientData;
2588
2589static FileHandler_ClientData *HeadFHCD;
2590
2591static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002592NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002593{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002594 FileHandler_ClientData *p;
2595 p = PyMem_NEW(FileHandler_ClientData, 1);
2596 if (p != NULL) {
2597 Py_XINCREF(func);
2598 Py_XINCREF(file);
2599 p->func = func;
2600 p->file = file;
2601 p->id = id;
2602 p->next = HeadFHCD;
2603 HeadFHCD = p;
2604 }
2605 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002606}
2607
2608static void
Fred Drake509d79a2000-07-08 04:04:38 +00002609DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002610{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002611 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002613 pp = &HeadFHCD;
2614 while ((p = *pp) != NULL) {
2615 if (p->id == id) {
2616 *pp = p->next;
2617 Py_XDECREF(p->func);
2618 Py_XDECREF(p->file);
2619 PyMem_DEL(p);
2620 }
2621 else
2622 pp = &p->next;
2623 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002624}
2625
Guido van Rossuma597dde1995-01-10 20:56:29 +00002626static void
Fred Drake509d79a2000-07-08 04:04:38 +00002627FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002628{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002629 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
INADA Naoki72dccde2017-02-16 09:26:01 +09002630 PyObject *func, *file, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002632 ENTER_PYTHON
2633 func = data->func;
2634 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002635
INADA Naoki72dccde2017-02-16 09:26:01 +09002636 res = PyObject_CallFunction(func, "Oi", file, mask);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002637 if (res == NULL) {
2638 errorInCmd = 1;
2639 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2640 }
2641 Py_XDECREF(res);
2642 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002643}
2644
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002645/*[clinic input]
2646_tkinter.tkapp.createfilehandler
2647
2648 file: object
2649 mask: int
2650 func: object
2651 /
2652
2653[clinic start generated code]*/
2654
Guido van Rossum18468821994-06-20 07:49:28 +00002655static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002656_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2657 int mask, PyObject *func)
2658/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002659{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002660 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002661 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002662
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002663 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002664
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002665 tfile = PyObject_AsFileDescriptor(file);
2666 if (tfile < 0)
2667 return NULL;
2668 if (!PyCallable_Check(func)) {
2669 PyErr_SetString(PyExc_TypeError, "bad argument list");
2670 return NULL;
2671 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002673 data = NewFHCD(func, file, tfile);
2674 if (data == NULL)
2675 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002676
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002677 /* Ought to check for null Tcl_File object... */
2678 ENTER_TCL
2679 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2680 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002681 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002682}
2683
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002684/*[clinic input]
2685_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002686
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002687 file: object
2688 /
2689
2690[clinic start generated code]*/
2691
2692static PyObject *
2693_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2694/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2695{
2696 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002697
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002698 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002700 tfile = PyObject_AsFileDescriptor(file);
2701 if (tfile < 0)
2702 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002703
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002704 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002705
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002706 /* Ought to check for null Tcl_File object... */
2707 ENTER_TCL
2708 Tcl_DeleteFileHandler(tfile);
2709 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002710 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002711}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002712#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002713
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002714
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002715/**** Tktt Object (timer token) ****/
2716
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002717static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002718
Guido van Rossum00d93061998-05-28 23:06:38 +00002719typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002720 PyObject_HEAD
2721 Tcl_TimerToken token;
2722 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002723} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002724
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002725/*[clinic input]
2726_tkinter.tktimertoken.deletetimerhandler
2727
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002728[clinic start generated code]*/
2729
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002730static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002731_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002732/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002733{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002734 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002735 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002736
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002737 if (v->token != NULL) {
2738 Tcl_DeleteTimerHandler(v->token);
2739 v->token = NULL;
2740 }
2741 if (func != NULL) {
2742 v->func = NULL;
2743 Py_DECREF(func);
2744 Py_DECREF(v); /* See Tktt_New() */
2745 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002746 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002747}
2748
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002749static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002750Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002751{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002752 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002753
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002754 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002755 if (v == NULL)
2756 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002757
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002758 Py_INCREF(func);
2759 v->token = NULL;
2760 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002761
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002762 /* Extra reference, deleted when called or when handler is deleted */
2763 Py_INCREF(v);
2764 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002765}
2766
2767static void
Fred Drake509d79a2000-07-08 04:04:38 +00002768Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002769{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002770 TkttObject *v = (TkttObject *)self;
2771 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002772 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002773
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002774 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002775
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002776 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002777 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002778}
2779
Guido van Rossum597ac201998-05-12 14:36:19 +00002780static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002781Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002782{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002783 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002784 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2785 v,
2786 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002787}
2788
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002789/** Timer Handler **/
2790
2791static void
Fred Drake509d79a2000-07-08 04:04:38 +00002792TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002793{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 TkttObject *v = (TkttObject *)clientData;
2795 PyObject *func = v->func;
2796 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002798 if (func == NULL)
2799 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002800
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002801 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002802
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002803 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002804
Victor Stinner2ff58a22019-06-17 14:27:23 +02002805 res = PyObject_CallNoArgs(func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002806 Py_DECREF(func);
2807 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002808
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002809 if (res == NULL) {
2810 errorInCmd = 1;
2811 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2812 }
2813 else
2814 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002815
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002816 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002817}
2818
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002819/*[clinic input]
2820_tkinter.tkapp.createtimerhandler
2821
2822 milliseconds: int
2823 func: object
2824 /
2825
2826[clinic start generated code]*/
2827
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002828static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002829_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2830 PyObject *func)
2831/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002832{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002833 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002834
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002835 if (!PyCallable_Check(func)) {
2836 PyErr_SetString(PyExc_TypeError, "bad argument list");
2837 return NULL;
2838 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002839
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002840 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002841
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002842 v = Tktt_New(func);
2843 if (v) {
2844 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2845 (ClientData)v);
2846 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002847
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002848 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002849}
2850
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002851
Guido van Rossum18468821994-06-20 07:49:28 +00002852/** Event Loop **/
2853
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002854/*[clinic input]
2855_tkinter.tkapp.mainloop
2856
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002857 threshold: int = 0
2858 /
2859
2860[clinic start generated code]*/
2861
Guido van Rossum18468821994-06-20 07:49:28 +00002862static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002863_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002864/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002865{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002866 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002867
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002868 CHECK_TCL_APPARTMENT;
2869 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002870
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002871 quitMainLoop = 0;
2872 while (Tk_GetNumMainWindows() > threshold &&
2873 !quitMainLoop &&
2874 !errorInCmd)
2875 {
2876 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002877
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002878 if (self->threaded) {
2879 /* Allow other Python threads to run. */
2880 ENTER_TCL
2881 result = Tcl_DoOneEvent(0);
2882 LEAVE_TCL
2883 }
2884 else {
2885 Py_BEGIN_ALLOW_THREADS
2886 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2887 tcl_tstate = tstate;
2888 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2889 tcl_tstate = NULL;
2890 if(tcl_lock)PyThread_release_lock(tcl_lock);
2891 if (result == 0)
2892 Sleep(Tkinter_busywaitinterval);
2893 Py_END_ALLOW_THREADS
2894 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002895
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002896 if (PyErr_CheckSignals() != 0) {
2897 self->dispatching = 0;
2898 return NULL;
2899 }
2900 if (result < 0)
2901 break;
2902 }
2903 self->dispatching = 0;
2904 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002905
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002906 if (errorInCmd) {
2907 errorInCmd = 0;
2908 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2909 excInCmd = valInCmd = trbInCmd = NULL;
2910 return NULL;
2911 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002912 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002913}
2914
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002915/*[clinic input]
2916_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002917
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002918 flags: int = 0
2919 /
2920
2921[clinic start generated code]*/
2922
2923static PyObject *
2924_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2925/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2926{
2927 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002928
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002929 ENTER_TCL
2930 rv = Tcl_DoOneEvent(flags);
2931 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002932 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002933}
2934
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002935/*[clinic input]
2936_tkinter.tkapp.quit
2937[clinic start generated code]*/
2938
Guido van Rossum062cfb01995-01-10 17:42:51 +00002939static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002940_tkinter_tkapp_quit_impl(TkappObject *self)
2941/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002942{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002943 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002944 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002945}
2946
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002947/*[clinic input]
2948_tkinter.tkapp.interpaddr
2949[clinic start generated code]*/
2950
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002951static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002952_tkinter_tkapp_interpaddr_impl(TkappObject *self)
2953/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002954{
Victor Stinnere1040e22013-09-05 00:22:24 +02002955 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002956}
2957
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002958/*[clinic input]
2959_tkinter.tkapp.loadtk
2960[clinic start generated code]*/
2961
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002962static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002963_tkinter_tkapp_loadtk_impl(TkappObject *self)
2964/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00002965{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002966 Tcl_Interp *interp = Tkapp_Interp(self);
2967 const char * _tk_exists = NULL;
2968 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002969
Guilherme Polob681df42009-02-09 22:33:59 +00002970#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002971 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2972 * first call failed.
2973 * To avoid the deadlock, we just refuse the second call through
2974 * a static variable.
2975 */
2976 if (tk_load_failed) {
2977 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2978 return NULL;
2979 }
Guilherme Polob681df42009-02-09 22:33:59 +00002980#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002981
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002982 /* We want to guard against calling Tk_Init() multiple times */
2983 CHECK_TCL_APPARTMENT;
2984 ENTER_TCL
2985 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2986 ENTER_OVERLAP
2987 if (err == TCL_ERROR) {
2988 /* This sets an exception, but we cannot return right
2989 away because we need to exit the overlap first. */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002990 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002991 } else {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002992 _tk_exists = Tcl_GetStringResult(Tkapp_Interp(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002993 }
2994 LEAVE_OVERLAP_TCL
2995 if (err == TCL_ERROR) {
2996 return NULL;
2997 }
2998 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2999 if (Tk_Init(interp) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03003000 Tkinter_Error(self);
Guilherme Polob681df42009-02-09 22:33:59 +00003001#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003002 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00003003#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003004 return NULL;
3005 }
3006 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003007 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00003008}
Barry Warsawfa701a81997-01-16 00:15:11 +00003009
Martin v. Löwisffad6332002-11-26 09:28:05 +00003010static PyObject *
3011Tkapp_WantObjects(PyObject *self, PyObject *args)
3012{
3013
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003014 int wantobjects = -1;
3015 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3016 return NULL;
3017 if (wantobjects == -1)
3018 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3019 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003020
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003021 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003022}
3023
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003024/*[clinic input]
3025_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003026
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003027[clinic start generated code]*/
3028
3029static PyObject *
3030_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03003031/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003032{
3033 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003034
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003035 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003036}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003037
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003038
Guido van Rossum18468821994-06-20 07:49:28 +00003039/**** Tkapp Type Methods ****/
3040
3041static void
Fred Drake509d79a2000-07-08 04:04:38 +00003042Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003043{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003044 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003045 /*CHECK_TCL_APPARTMENT;*/
3046 ENTER_TCL
3047 Tcl_DeleteInterp(Tkapp_Interp(self));
3048 LEAVE_TCL
3049 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003050 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003051 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003052}
3053
Barry Warsawfa701a81997-01-16 00:15:11 +00003054
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003055
Guido van Rossum18468821994-06-20 07:49:28 +00003056/**** Tkinter Module ****/
3057
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003058typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003059 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003060 Py_ssize_t size; /* current size */
3061 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003062} FlattenContext;
3063
3064static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003065_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003066{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003067 /* expand tuple to hold (at least) size new items.
3068 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003069
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003070 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003071
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003072 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003073 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003074
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003075 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003076
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003077 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003078}
3079
3080static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003081_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003082{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003083 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003084
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003085 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003086
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003087 if (depth > 1000) {
3088 PyErr_SetString(PyExc_ValueError,
3089 "nesting too deep in _flatten");
3090 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003091 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3092 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003093 /* preallocate (assume no nesting) */
3094 if (context->size + size > context->maxsize &&
3095 !_bump(context, size))
3096 return 0;
3097 /* copy items to output tuple */
3098 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003099 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003100 if (PyList_Check(o) || PyTuple_Check(o)) {
3101 if (!_flatten1(context, o, depth + 1))
3102 return 0;
3103 } else if (o != Py_None) {
3104 if (context->size + 1 > context->maxsize &&
3105 !_bump(context, 1))
3106 return 0;
3107 Py_INCREF(o);
3108 PyTuple_SET_ITEM(context->tuple,
3109 context->size++, o);
3110 }
3111 }
3112 } else {
3113 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3114 return 0;
3115 }
3116 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003117}
3118
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003119/*[clinic input]
3120_tkinter._flatten
3121
3122 item: object
3123 /
3124
3125[clinic start generated code]*/
3126
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003127static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003128_tkinter__flatten(PyObject *module, PyObject *item)
3129/*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003130{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003131 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003132
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003133 context.maxsize = PySequence_Size(item);
3134 if (context.maxsize < 0)
3135 return NULL;
3136 if (context.maxsize == 0)
3137 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003138
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003139 context.tuple = PyTuple_New(context.maxsize);
3140 if (!context.tuple)
3141 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003142
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003143 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003144
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003145 if (!_flatten1(&context, item,0))
3146 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003147
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003148 if (_PyTuple_Resize(&context.tuple, context.size))
3149 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003150
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003151 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003152}
3153
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003154/*[clinic input]
3155_tkinter.create
3156
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003157 screenName: str(accept={str, NoneType}) = None
3158 baseName: str = ""
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003159 className: str = "Tk"
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003160 interactive: bool(accept={int}) = False
3161 wantobjects: bool(accept={int}) = False
3162 wantTk: bool(accept={int}) = True
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003163 if false, then Tk_Init() doesn't get called
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003164 sync: bool(accept={int}) = False
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003165 if true, then pass -sync to wish
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003166 use: str(accept={str, NoneType}) = None
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003167 if not None, then pass -use to wish
3168 /
3169
3170[clinic start generated code]*/
3171
Guido van Rossum18468821994-06-20 07:49:28 +00003172static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003173_tkinter_create_impl(PyObject *module, const char *screenName,
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003174 const char *baseName, const char *className,
3175 int interactive, int wantobjects, int wantTk, int sync,
3176 const char *use)
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003177/*[clinic end generated code: output=e3315607648e6bb4 input=da9b17ee7358d862]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003178{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003179 /* XXX baseName is not used anymore;
3180 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003181 CHECK_STRING_LENGTH(screenName);
3182 CHECK_STRING_LENGTH(baseName);
3183 CHECK_STRING_LENGTH(className);
3184 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003185
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003186 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003187 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003188 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003189}
3190
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003191/*[clinic input]
3192_tkinter.setbusywaitinterval
3193
3194 new_val: int
3195 /
3196
3197Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3198
3199It should be set to a divisor of the maximum time between frames in an animation.
3200[clinic start generated code]*/
3201
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003202static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003203_tkinter_setbusywaitinterval_impl(PyObject *module, int new_val)
3204/*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003205{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003206 if (new_val < 0) {
3207 PyErr_SetString(PyExc_ValueError,
3208 "busywaitinterval must be >= 0");
3209 return NULL;
3210 }
3211 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003212 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003213}
3214
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003215/*[clinic input]
3216_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003217
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003218Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3219[clinic start generated code]*/
3220
3221static int
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003222_tkinter_getbusywaitinterval_impl(PyObject *module)
3223/*[clinic end generated code: output=23b72d552001f5c7 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003224{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003225 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003226}
3227
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003228#include "clinic/_tkinter.c.h"
3229
3230static PyMethodDef Tktt_methods[] =
3231{
3232 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3233 {NULL, NULL}
3234};
3235
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003236static PyType_Slot Tktt_Type_slots[] = {
3237 {Py_tp_dealloc, Tktt_Dealloc},
3238 {Py_tp_repr, Tktt_Repr},
3239 {Py_tp_methods, Tktt_methods},
3240 {0, 0}
3241};
3242
3243static PyType_Spec Tktt_Type_spec = {
3244 "_tkinter.tktimertoken",
3245 sizeof(TkttObject),
3246 0,
3247 Py_TPFLAGS_DEFAULT,
3248 Tktt_Type_slots,
3249};
3250
3251
3252/**** Tkapp Method List ****/
3253
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003254static PyMethodDef Tkapp_methods[] =
3255{
3256 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3257 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3258 {"call", Tkapp_Call, METH_VARARGS},
3259 _TKINTER_TKAPP_EVAL_METHODDEF
3260 _TKINTER_TKAPP_EVALFILE_METHODDEF
3261 _TKINTER_TKAPP_RECORD_METHODDEF
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03003262 _TKINTER_TKAPP_ADDERRORINFO_METHODDEF
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003263 {"setvar", Tkapp_SetVar, METH_VARARGS},
3264 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3265 {"getvar", Tkapp_GetVar, METH_VARARGS},
3266 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3267 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3268 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3269 _TKINTER_TKAPP_GETINT_METHODDEF
3270 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3271 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3272 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3273 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3274 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3275 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3276 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3277 _TKINTER_TKAPP_SPLIT_METHODDEF
3278 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3279 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3280 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3281 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3282 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3283 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3284 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3285 _TKINTER_TKAPP_QUIT_METHODDEF
3286 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3287 _TKINTER_TKAPP_LOADTK_METHODDEF
3288 {NULL, NULL}
3289};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003290
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003291static PyType_Slot Tkapp_Type_slots[] = {
3292 {Py_tp_dealloc, Tkapp_Dealloc},
3293 {Py_tp_methods, Tkapp_methods},
3294 {0, 0}
3295};
3296
3297
3298static PyType_Spec Tkapp_Type_spec = {
3299 "_tkinter.tkapp",
3300 sizeof(TkappObject),
3301 0,
3302 Py_TPFLAGS_DEFAULT,
3303 Tkapp_Type_slots,
3304};
3305
Guido van Rossum18468821994-06-20 07:49:28 +00003306static PyMethodDef moduleMethods[] =
3307{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003308 _TKINTER__FLATTEN_METHODDEF
3309 _TKINTER_CREATE_METHODDEF
3310 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3311 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003312 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003313};
3314
Guido van Rossum7bf15641998-05-22 18:28:17 +00003315#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003316
3317static int stdin_ready = 0;
3318
Guido van Rossumad4db171998-06-13 13:56:28 +00003319#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003320static void
Fred Drake509d79a2000-07-08 04:04:38 +00003321MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003322{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003323 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003324}
Guido van Rossumad4db171998-06-13 13:56:28 +00003325#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003326
Guido van Rossum00d93061998-05-28 23:06:38 +00003327static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003328
Guido van Rossum18468821994-06-20 07:49:28 +00003329static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003330EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003331{
Guido van Rossumad4db171998-06-13 13:56:28 +00003332#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003333 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003334#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003335 PyEval_RestoreThread(event_tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003336 stdin_ready = 0;
3337 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003338#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003339 tfile = fileno(stdin);
3340 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003341#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003342 while (!errorInCmd && !stdin_ready) {
3343 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003344#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003345 if (_kbhit()) {
3346 stdin_ready = 1;
3347 break;
3348 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003349#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003350 Py_BEGIN_ALLOW_THREADS
3351 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3352 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003353
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003354 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003356 tcl_tstate = NULL;
3357 if(tcl_lock)PyThread_release_lock(tcl_lock);
3358 if (result == 0)
3359 Sleep(Tkinter_busywaitinterval);
3360 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003362 if (result < 0)
3363 break;
3364 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003365#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003366 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003367#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003368 if (errorInCmd) {
3369 errorInCmd = 0;
3370 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3371 excInCmd = valInCmd = trbInCmd = NULL;
3372 PyErr_Print();
3373 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003374 PyEval_SaveThread();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003375 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003376}
Guido van Rossum18468821994-06-20 07:49:28 +00003377
Guido van Rossum00d93061998-05-28 23:06:38 +00003378#endif
3379
Guido van Rossum7bf15641998-05-22 18:28:17 +00003380static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003381EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003382{
Guido van Rossum00d93061998-05-28 23:06:38 +00003383#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003384 if (PyOS_InputHook == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003385 event_tstate = PyThreadState_Get();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003386 PyOS_InputHook = EventHook;
3387 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003388#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003389}
3390
3391static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003392DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003393{
Guido van Rossum00d93061998-05-28 23:06:38 +00003394#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003395 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3396 PyOS_InputHook = NULL;
3397 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003398#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003399}
3400
Barry Warsawfa701a81997-01-16 00:15:11 +00003401
Martin v. Löwis1a214512008-06-11 05:26:20 +00003402static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003403 PyModuleDef_HEAD_INIT,
3404 "_tkinter",
3405 NULL,
3406 -1,
3407 moduleMethods,
3408 NULL,
3409 NULL,
3410 NULL,
3411 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003412};
3413
Mark Hammond62b1ab12002-07-23 06:31:15 +00003414PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003415PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003416{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003417 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003418
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003419 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003420 if (tcl_lock == NULL)
3421 return NULL;
Guido van Rossumae92f011996-08-21 19:03:36 +00003422
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003423 m = PyModule_Create(&_tkintermodule);
3424 if (m == NULL)
3425 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003426
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003427 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3428 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003429 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003430 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003431 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003432 Py_INCREF(o);
3433 if (PyModule_AddObject(m, "TclError", o)) {
3434 Py_DECREF(o);
3435 Py_DECREF(m);
3436 return NULL;
3437 }
3438 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003439
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003440 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3441 Py_DECREF(m);
3442 return NULL;
3443 }
3444 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3445 Py_DECREF(m);
3446 return NULL;
3447 }
3448 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3449 Py_DECREF(m);
3450 return NULL;
3451 }
3452 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3453 Py_DECREF(m);
3454 return NULL;
3455 }
3456 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3457 Py_DECREF(m);
3458 return NULL;
3459 }
3460 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3461 Py_DECREF(m);
3462 return NULL;
3463 }
3464 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3465 Py_DECREF(m);
3466 return NULL;
3467 }
3468 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3469 Py_DECREF(m);
3470 return NULL;
3471 }
3472 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3473 Py_DECREF(m);
3474 return NULL;
3475 }
3476 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3477 Py_DECREF(m);
3478 return NULL;
3479 }
3480 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3481 Py_DECREF(m);
3482 return NULL;
3483 }
3484
3485 o = PyType_FromSpec(&Tkapp_Type_spec);
3486 if (o == NULL) {
3487 Py_DECREF(m);
3488 return NULL;
3489 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003490 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003491 if (PyModule_AddObject(m, "TkappType", o)) {
3492 Py_DECREF(o);
3493 Py_DECREF(m);
3494 return NULL;
3495 }
3496 Tkapp_Type = o;
3497
3498 o = PyType_FromSpec(&Tktt_Type_spec);
3499 if (o == NULL) {
3500 Py_DECREF(m);
3501 return NULL;
3502 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003503 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003504 if (PyModule_AddObject(m, "TkttType", o)) {
3505 Py_DECREF(o);
3506 Py_DECREF(m);
3507 return NULL;
3508 }
3509 Tktt_Type = o;
3510
3511 o = PyType_FromSpec(&PyTclObject_Type_spec);
3512 if (o == NULL) {
3513 Py_DECREF(m);
3514 return NULL;
3515 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003516 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003517 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3518 Py_DECREF(o);
3519 Py_DECREF(m);
3520 return NULL;
3521 }
3522 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003523
3524#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003525 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3526 * start waking up. Note that Tcl_FindExecutable will do this, this
3527 * code must be above it! The original warning from
3528 * tkMacOSXAppInit.c is copied below.
3529 *
3530 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3531 * Tcl interpreter for now. It probably should work to do this
3532 * in the other order, but for now it doesn't seem to.
3533 *
3534 */
3535 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003536#endif
3537
3538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003539 /* This helps the dynamic loader; in Unicode aware Tcl versions
3540 it also helps Tcl find its encodings. */
3541 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3542 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003543 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003544 if (cexe) {
3545#ifdef MS_WINDOWS
3546 int set_var = 0;
3547 PyObject *str_path;
3548 wchar_t *wcs_path;
3549 DWORD ret;
3550
3551 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3552
3553 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3554 str_path = _get_tcl_lib_path();
3555 if (str_path == NULL && PyErr_Occurred()) {
Brandt Bucher289cf0f2019-11-18 06:52:36 -08003556 Py_DECREF(m);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003557 return NULL;
3558 }
3559 if (str_path != NULL) {
3560 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3561 if (wcs_path == NULL) {
Brandt Bucher289cf0f2019-11-18 06:52:36 -08003562 Py_DECREF(m);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003563 return NULL;
3564 }
3565 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3566 set_var = 1;
3567 }
3568 }
3569
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003570 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003571
3572 if (set_var) {
3573 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3574 PyMem_Free(wcs_path);
3575 }
3576#else
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003577 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003578#endif /* MS_WINDOWS */
3579 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003580 Py_XDECREF(cexe);
3581 Py_DECREF(uexe);
3582 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003583
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003584 if (PyErr_Occurred()) {
3585 Py_DECREF(m);
3586 return NULL;
3587 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003588
Guido van Rossum43ff8681998-07-14 18:02:13 +00003589#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003590 /* This was not a good idea; through <Destroy> bindings,
3591 Tcl_Finalize() may invoke Python code but at that point the
3592 interpreter and thread state have already been destroyed! */
3593 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003594#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003595 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003596}