blob: 235cb6bc28dd5c22d370c38b221c0b5aba4f5cf7 [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;
836#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000837
838static PyObject *
839newPyTclObject(Tcl_Obj *arg)
840{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000841 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300842 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000843 if (self == NULL)
844 return NULL;
845 Tcl_IncrRefCount(arg);
846 self->value = arg;
847 self->string = NULL;
848 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000849}
850
851static void
852PyTclObject_dealloc(PyTclObject *self)
853{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200854 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000855 Tcl_DecrRefCount(self->value);
856 Py_XDECREF(self->string);
857 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200858 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000859}
860
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000861/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000862PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000863"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000864
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000865static PyObject *
866PyTclObject_string(PyTclObject *self, void *ignored)
867{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000868 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200869 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000870 if (!self->string)
871 return NULL;
872 }
873 Py_INCREF(self->string);
874 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000875}
876
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000877static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200878PyTclObject_str(PyTclObject *self)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000879{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200880 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 Py_INCREF(self->string);
882 return self->string;
883 }
884 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200885 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000886}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000887
Martin v. Löwisffad6332002-11-26 09:28:05 +0000888static PyObject *
889PyTclObject_repr(PyTclObject *self)
890{
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200891 PyObject *repr, *str = PyTclObject_str(self);
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300892 if (str == NULL)
893 return NULL;
894 repr = PyUnicode_FromFormat("<%s object: %R>",
895 self->value->typePtr->name, str);
896 Py_DECREF(str);
897 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000898}
899
Mark Dickinson211c6252009-02-01 10:28:51 +0000900static PyObject *
901PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000902{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000903 int result;
Mark Dickinson211c6252009-02-01 10:28:51 +0000904
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000905 /* neither argument should be NULL, unless something's gone wrong */
906 if (self == NULL || other == NULL) {
907 PyErr_BadInternalCall();
908 return NULL;
909 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000910
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000911 /* both arguments should be instances of PyTclObject */
912 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
stratakise8b19652017-11-02 11:32:54 +0100913 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000914 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000915
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000916 if (self == other)
917 /* fast path when self and other are identical */
918 result = 0;
919 else
920 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
921 Tcl_GetString(((PyTclObject *)other)->value));
stratakise8b19652017-11-02 11:32:54 +0100922 Py_RETURN_RICHCOMPARE(result, 0, op);
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000923}
924
Martin v. Löwis39195712003-01-04 00:33:13 +0000925PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
926
Martin v. Löwisffad6332002-11-26 09:28:05 +0000927static PyObject*
928get_typename(PyTclObject* obj, void* ignored)
929{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200930 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000931}
932
Martin v. Löwis39195712003-01-04 00:33:13 +0000933
Martin v. Löwisffad6332002-11-26 09:28:05 +0000934static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000935 {"typename", (getter)get_typename, NULL, get_typename__doc__},
936 {"string", (getter)PyTclObject_string, NULL,
937 PyTclObject_string__doc__},
938 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000939};
940
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300941static PyType_Slot PyTclObject_Type_slots[] = {
942 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
943 {Py_tp_repr, (reprfunc)PyTclObject_repr},
944 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200945 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300946 {Py_tp_richcompare, PyTclObject_richcompare},
947 {Py_tp_getset, PyTclObject_getsetlist},
948 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000949};
950
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300951static PyType_Spec PyTclObject_Type_spec = {
952 "_tkinter.Tcl_Obj",
953 sizeof(PyTclObject),
954 0,
955 Py_TPFLAGS_DEFAULT,
956 PyTclObject_Type_slots,
957};
958
959
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700960#if SIZE_MAX > INT_MAX
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300961#define CHECK_STRING_LENGTH(s) do { \
962 if (s != NULL && strlen(s) >= INT_MAX) { \
963 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
964 return NULL; \
965 } } while(0)
966#else
967#define CHECK_STRING_LENGTH(s)
968#endif
969
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300970#ifdef HAVE_LIBTOMMAMTH
971static Tcl_Obj*
972asBignumObj(PyObject *value)
973{
974 Tcl_Obj *result;
975 int neg;
976 PyObject *hexstr;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200977 const char *hexchars;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300978 mp_int bigValue;
979
980 neg = Py_SIZE(value) < 0;
981 hexstr = _PyLong_Format(value, 16);
982 if (hexstr == NULL)
983 return NULL;
984 hexchars = PyUnicode_AsUTF8(hexstr);
985 if (hexchars == NULL) {
986 Py_DECREF(hexstr);
987 return NULL;
988 }
989 hexchars += neg + 2; /* skip sign and "0x" */
990 mp_init(&bigValue);
991 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
992 mp_clear(&bigValue);
993 Py_DECREF(hexstr);
994 PyErr_NoMemory();
995 return NULL;
996 }
997 Py_DECREF(hexstr);
998 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
999 result = Tcl_NewBignumObj(&bigValue);
1000 mp_clear(&bigValue);
1001 if (result == NULL) {
1002 PyErr_NoMemory();
1003 return NULL;
1004 }
1005 return result;
1006}
1007#endif
1008
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001009static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001010AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001011{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001012 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001013
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001014 if (PyBytes_Check(value)) {
1015 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
1016 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1017 return NULL;
1018 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +03001019 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001020 (int)PyBytes_GET_SIZE(value));
1021 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001022
1023 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001024 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001025
1026 if (PyLong_CheckExact(value)) {
1027 int overflow;
1028 long longValue;
1029#ifdef TCL_WIDE_INT_TYPE
1030 Tcl_WideInt wideValue;
1031#endif
1032 longValue = PyLong_AsLongAndOverflow(value, &overflow);
1033 if (!overflow) {
1034 return Tcl_NewLongObj(longValue);
1035 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001036 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001037 fall through to wideInt handling. */
1038#ifdef TCL_WIDE_INT_TYPE
1039 if (_PyLong_AsByteArray((PyLongObject *)value,
1040 (unsigned char *)(void *)&wideValue,
1041 sizeof(wideValue),
1042 PY_LITTLE_ENDIAN,
1043 /* signed */ 1) == 0) {
1044 return Tcl_NewWideIntObj(wideValue);
1045 }
1046 PyErr_Clear();
1047#endif
1048 /* If there is an overflow in the wideInt conversion,
1049 fall through to bignum handling. */
1050#ifdef HAVE_LIBTOMMAMTH
1051 return asBignumObj(value);
1052#endif
1053 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001054 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001056
1057 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001058 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001059
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +03001060 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001061 Tcl_Obj **argv;
1062 Py_ssize_t size, i;
1063
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001064 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001065 if (size == 0)
1066 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001067 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001068 PyErr_SetString(PyExc_OverflowError,
1069 PyTuple_Check(value) ? "tuple is too long" :
1070 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001071 return NULL;
1072 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001073 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
1074 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001075 PyErr_NoMemory();
1076 return NULL;
1077 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001078 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001079 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001080 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001081 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001082 return result;
1083 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001084
1085 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001086 if (PyUnicode_READY(value) == -1)
1087 return NULL;
1088
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",
1737 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001739}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001740
Benjamin Peterson5879d412009-03-30 14:51:56 +00001741
Martin v. Löwis59683e82008-06-13 07:50:45 +00001742static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001743var_perform(VarEvent *ev)
1744{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001745 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1746 if (!*(ev->res)) {
1747 PyObject *exc, *val, *tb;
1748 PyErr_Fetch(&exc, &val, &tb);
1749 PyErr_NormalizeException(&exc, &val, &tb);
1750 *(ev->exc_type) = exc;
1751 *(ev->exc_val) = val;
Serhiy Storchaka3ec5f422016-10-28 12:14:34 +03001752 Py_XDECREF(tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001753 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001754
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001755}
1756
1757static int
1758var_proc(VarEvent* ev, int flags)
1759{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001760 ENTER_PYTHON
1761 var_perform(ev);
1762 Tcl_MutexLock(&var_mutex);
1763 Tcl_ConditionNotify(ev->cond);
1764 Tcl_MutexUnlock(&var_mutex);
1765 LEAVE_PYTHON
1766 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001767}
1768
Benjamin Peterson5879d412009-03-30 14:51:56 +00001769
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001770static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001771var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001772{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001773 TkappObject *self = (TkappObject*)selfptr;
1774 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 VarEvent *ev;
1776 PyObject *res, *exc_type, *exc_val;
1777 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001778
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001779 /* The current thread is not the interpreter thread. Marshal
1780 the call to the interpreter thread, then wait for
1781 completion. */
1782 if (!WaitForMainloop(self))
1783 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001784
Serhiy Storchaka07940882014-09-11 10:38:54 +03001785 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1786 if (ev == NULL) {
1787 PyErr_NoMemory();
1788 return NULL;
1789 }
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;
2169 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2170 ENTER_TCL
2171 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2172 ENTER_OVERLAP
2173 PyFPE_END_PROTECT(retval)
2174 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002175 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002176 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002177 res = PyFloat_FromDouble(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002178 LEAVE_OVERLAP_TCL
2179 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002180}
2181
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002182/*[clinic input]
2183_tkinter.tkapp.exprboolean
2184
2185 s: str
2186 /
2187
2188[clinic start generated code]*/
2189
Guido van Rossum18468821994-06-20 07:49:28 +00002190static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002191_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2192/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002193{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002194 PyObject *res = NULL;
2195 int retval;
2196 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002197
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002198 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002199 CHECK_TCL_APPARTMENT;
2200 ENTER_TCL
2201 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2202 ENTER_OVERLAP
2203 if (retval == TCL_ERROR)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002204 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002205 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002206 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002207 LEAVE_OVERLAP_TCL
2208 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002209}
2210
Barry Warsawfa701a81997-01-16 00:15:11 +00002211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002212
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002213/*[clinic input]
2214_tkinter.tkapp.splitlist
2215
2216 arg: object
2217 /
2218
2219[clinic start generated code]*/
2220
Guido van Rossum18468821994-06-20 07:49:28 +00002221static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002222_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2223/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002224{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002225 char *list;
2226 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002227 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002228 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002229 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002230
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002231 if (PyTclObject_Check(arg)) {
2232 int objc;
2233 Tcl_Obj **objv;
2234 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2235 ((PyTclObject*)arg)->value,
2236 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002237 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002238 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002239 if (!(v = PyTuple_New(objc)))
2240 return NULL;
2241 for (i = 0; i < objc; i++) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002242 PyObject *s = FromObj(self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002243 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002244 Py_DECREF(v);
2245 return NULL;
2246 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002247 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002248 }
2249 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002250 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002251 if (PyTuple_Check(arg)) {
2252 Py_INCREF(arg);
2253 return arg;
2254 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002255 if (PyList_Check(arg)) {
2256 return PySequence_Tuple(arg);
2257 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002258
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002259 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002260 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002261
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002262 if (strlen(list) >= INT_MAX) {
2263 PyErr_SetString(PyExc_OverflowError, "string is too long");
2264 PyMem_Free(list);
2265 return NULL;
2266 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002267 if (Tcl_SplitList(Tkapp_Interp(self), list,
2268 &argc, &argv) == TCL_ERROR) {
2269 PyMem_Free(list);
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002270 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002271 }
Guido van Rossum18468821994-06-20 07:49:28 +00002272
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002273 if (!(v = PyTuple_New(argc)))
2274 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002275
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002276 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002277 PyObject *s = unicodeFromTclString(argv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002278 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002279 Py_DECREF(v);
2280 v = NULL;
2281 goto finally;
2282 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002283 PyTuple_SET_ITEM(v, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002284 }
Guido van Rossum18468821994-06-20 07:49:28 +00002285
Barry Warsawfa701a81997-01-16 00:15:11 +00002286 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002287 ckfree(FREECAST argv);
2288 PyMem_Free(list);
2289 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002290}
2291
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002292/*[clinic input]
2293_tkinter.tkapp.split
2294
2295 arg: object
2296 /
2297
2298[clinic start generated code]*/
2299
Guido van Rossum18468821994-06-20 07:49:28 +00002300static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002301_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2302/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002303{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002304 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002305 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002306
Serhiy Storchakad05b0002019-10-08 14:31:35 +03002307 if (PyErr_WarnEx(PyExc_DeprecationWarning,
2308 "split() is deprecated; consider using splitlist() instead", 1))
2309 {
2310 return NULL;
2311 }
2312
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002313 if (PyTclObject_Check(arg)) {
2314 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2315 int objc;
2316 Tcl_Obj **objv;
2317 int i;
2318 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2319 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002320 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002321 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002322 if (objc == 0)
2323 return PyUnicode_FromString("");
2324 if (objc == 1)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002325 return FromObj(self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002326 if (!(v = PyTuple_New(objc)))
2327 return NULL;
2328 for (i = 0; i < objc; i++) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002329 PyObject *s = FromObj(self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002330 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002331 Py_DECREF(v);
2332 return NULL;
2333 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002334 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002335 }
2336 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002337 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002338 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002339 return SplitObj(arg);
2340
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002341 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002342 return NULL;
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002343 if (strlen(list) >= INT_MAX) {
2344 PyErr_SetString(PyExc_OverflowError, "string is too long");
2345 PyMem_Free(list);
2346 return NULL;
2347 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002348 v = Split(list);
2349 PyMem_Free(list);
2350 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002351}
2352
Barry Warsawfa701a81997-01-16 00:15:11 +00002353
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002354
Guido van Rossum18468821994-06-20 07:49:28 +00002355/** Tcl Command **/
2356
Guido van Rossum00d93061998-05-28 23:06:38 +00002357/* Client data struct */
2358typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002359 PyObject *self;
2360 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002361} PythonCmd_ClientData;
2362
2363static int
Fred Drake509d79a2000-07-08 04:04:38 +00002364PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002365{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002366 errorInCmd = 1;
2367 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2368 LEAVE_PYTHON
2369 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002370}
2371
Guido van Rossum18468821994-06-20 07:49:28 +00002372/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002373 * function or method.
2374 */
Guido van Rossum18468821994-06-20 07:49:28 +00002375static int
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002376PythonCmd(ClientData clientData, Tcl_Interp *interp,
2377 int objc, Tcl_Obj *const objv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002378{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002379 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002380 PyObject *args, *res;
2381 int i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002382 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002384 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002385
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002386 /* Create argument tuple (objv1, ..., objvN) */
2387 if (!(args = PyTuple_New(objc - 1)))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002388 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002389
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002390 for (i = 0; i < (objc - 1); i++) {
2391 PyObject *s = unicodeFromTclObj(objv[i + 1]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002392 if (!s) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002393 Py_DECREF(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002394 return PythonCmd_Error(interp);
2395 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002396 PyTuple_SET_ITEM(args, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002397 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002398
2399 res = PyObject_Call(data->func, args, NULL);
2400 Py_DECREF(args);
Guido van Rossum18468821994-06-20 07:49:28 +00002401
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002402 if (res == NULL)
2403 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002405 obj_res = AsObj(res);
2406 if (obj_res == NULL) {
2407 Py_DECREF(res);
2408 return PythonCmd_Error(interp);
2409 }
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002410 Tcl_SetObjResult(interp, obj_res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002411 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002413 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002414
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002415 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +00002416}
2417
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002418
Guido van Rossum18468821994-06-20 07:49:28 +00002419static void
Fred Drake509d79a2000-07-08 04:04:38 +00002420PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002421{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002422 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002423
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002424 ENTER_PYTHON
2425 Py_XDECREF(data->self);
2426 Py_XDECREF(data->func);
2427 PyMem_DEL(data);
2428 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002429}
2430
Barry Warsawfa701a81997-01-16 00:15:11 +00002431
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002432
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002433
2434TCL_DECLARE_MUTEX(command_mutex)
2435
2436typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002437 Tcl_Event ev;
2438 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002439 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002440 int create;
2441 int *status;
2442 ClientData *data;
2443 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002444} CommandEvent;
2445
2446static int
2447Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002448{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002449 if (ev->create)
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002450 *ev->status = Tcl_CreateObjCommand(
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002451 ev->interp, ev->name, PythonCmd,
2452 ev->data, PythonCmdDelete) == NULL;
2453 else
2454 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2455 Tcl_MutexLock(&command_mutex);
2456 Tcl_ConditionNotify(ev->done);
2457 Tcl_MutexUnlock(&command_mutex);
2458 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002459}
2460
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002461/*[clinic input]
2462_tkinter.tkapp.createcommand
2463
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002464 name: str
2465 func: object
2466 /
2467
2468[clinic start generated code]*/
2469
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002470static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002471_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2472 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002473/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002474{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002475 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002476 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002477
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002478 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002479 if (!PyCallable_Check(func)) {
2480 PyErr_SetString(PyExc_TypeError, "command not callable");
2481 return NULL;
2482 }
Guido van Rossum18468821994-06-20 07:49:28 +00002483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002484 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2485 !WaitForMainloop(self))
2486 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002488 data = PyMem_NEW(PythonCmd_ClientData, 1);
2489 if (!data)
2490 return PyErr_NoMemory();
2491 Py_INCREF(self);
2492 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002493 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002494 data->func = func;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002495 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2496 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002497 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2498 if (ev == NULL) {
2499 PyErr_NoMemory();
2500 PyMem_DEL(data);
2501 return NULL;
2502 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002503 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2504 ev->interp = self->interp;
2505 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002506 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002507 ev->data = (ClientData)data;
2508 ev->status = &err;
2509 ev->done = &cond;
2510 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2511 Tcl_ConditionFinalize(&cond);
2512 }
2513 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002514 {
2515 ENTER_TCL
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002516 err = Tcl_CreateObjCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002517 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002518 (ClientData)data, PythonCmdDelete) == NULL;
2519 LEAVE_TCL
2520 }
2521 if (err) {
2522 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2523 PyMem_DEL(data);
2524 return NULL;
2525 }
Guido van Rossum18468821994-06-20 07:49:28 +00002526
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002527 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002528}
2529
Barry Warsawfa701a81997-01-16 00:15:11 +00002530
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002531
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002532/*[clinic input]
2533_tkinter.tkapp.deletecommand
2534
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002535 name: str
2536 /
2537
2538[clinic start generated code]*/
2539
Guido van Rossum18468821994-06-20 07:49:28 +00002540static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002541_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002542/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002543{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002544 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002545
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002546 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002548 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2549 Tcl_Condition cond = NULL;
2550 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002551 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2552 if (ev == NULL) {
2553 PyErr_NoMemory();
2554 return NULL;
2555 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002556 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2557 ev->interp = self->interp;
2558 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002559 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560 ev->status = &err;
2561 ev->done = &cond;
2562 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2563 &command_mutex);
2564 Tcl_ConditionFinalize(&cond);
2565 }
2566 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002567 {
2568 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002569 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002570 LEAVE_TCL
2571 }
2572 if (err == -1) {
2573 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2574 return NULL;
2575 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002576 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002577}
2578
Barry Warsawfa701a81997-01-16 00:15:11 +00002579
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002580
Guido van Rossum00d93061998-05-28 23:06:38 +00002581#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002582/** File Handler **/
2583
Guido van Rossum00d93061998-05-28 23:06:38 +00002584typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002585 PyObject *func;
2586 PyObject *file;
2587 int id;
2588 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002589} FileHandler_ClientData;
2590
2591static FileHandler_ClientData *HeadFHCD;
2592
2593static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002594NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002595{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002596 FileHandler_ClientData *p;
2597 p = PyMem_NEW(FileHandler_ClientData, 1);
2598 if (p != NULL) {
2599 Py_XINCREF(func);
2600 Py_XINCREF(file);
2601 p->func = func;
2602 p->file = file;
2603 p->id = id;
2604 p->next = HeadFHCD;
2605 HeadFHCD = p;
2606 }
2607 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002608}
2609
2610static void
Fred Drake509d79a2000-07-08 04:04:38 +00002611DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002612{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002613 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002614
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002615 pp = &HeadFHCD;
2616 while ((p = *pp) != NULL) {
2617 if (p->id == id) {
2618 *pp = p->next;
2619 Py_XDECREF(p->func);
2620 Py_XDECREF(p->file);
2621 PyMem_DEL(p);
2622 }
2623 else
2624 pp = &p->next;
2625 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002626}
2627
Guido van Rossuma597dde1995-01-10 20:56:29 +00002628static void
Fred Drake509d79a2000-07-08 04:04:38 +00002629FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002630{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002631 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
INADA Naoki72dccde2017-02-16 09:26:01 +09002632 PyObject *func, *file, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002634 ENTER_PYTHON
2635 func = data->func;
2636 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002637
INADA Naoki72dccde2017-02-16 09:26:01 +09002638 res = PyObject_CallFunction(func, "Oi", file, mask);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002639 if (res == NULL) {
2640 errorInCmd = 1;
2641 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2642 }
2643 Py_XDECREF(res);
2644 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002645}
2646
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002647/*[clinic input]
2648_tkinter.tkapp.createfilehandler
2649
2650 file: object
2651 mask: int
2652 func: object
2653 /
2654
2655[clinic start generated code]*/
2656
Guido van Rossum18468821994-06-20 07:49:28 +00002657static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002658_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2659 int mask, PyObject *func)
2660/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002661{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002662 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002663 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002664
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002665 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002667 tfile = PyObject_AsFileDescriptor(file);
2668 if (tfile < 0)
2669 return NULL;
2670 if (!PyCallable_Check(func)) {
2671 PyErr_SetString(PyExc_TypeError, "bad argument list");
2672 return NULL;
2673 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002674
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002675 data = NewFHCD(func, file, tfile);
2676 if (data == NULL)
2677 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002678
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002679 /* Ought to check for null Tcl_File object... */
2680 ENTER_TCL
2681 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2682 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002683 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002684}
2685
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002686/*[clinic input]
2687_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002688
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002689 file: object
2690 /
2691
2692[clinic start generated code]*/
2693
2694static PyObject *
2695_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2696/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2697{
2698 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002700 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002702 tfile = PyObject_AsFileDescriptor(file);
2703 if (tfile < 0)
2704 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002705
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002706 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002707
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002708 /* Ought to check for null Tcl_File object... */
2709 ENTER_TCL
2710 Tcl_DeleteFileHandler(tfile);
2711 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002712 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002713}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002714#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002715
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002716
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002717/**** Tktt Object (timer token) ****/
2718
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002719static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002720
Guido van Rossum00d93061998-05-28 23:06:38 +00002721typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002722 PyObject_HEAD
2723 Tcl_TimerToken token;
2724 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002725} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002726
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002727/*[clinic input]
2728_tkinter.tktimertoken.deletetimerhandler
2729
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002730[clinic start generated code]*/
2731
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002732static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002733_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002734/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002735{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002736 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002737 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002738
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002739 if (v->token != NULL) {
2740 Tcl_DeleteTimerHandler(v->token);
2741 v->token = NULL;
2742 }
2743 if (func != NULL) {
2744 v->func = NULL;
2745 Py_DECREF(func);
2746 Py_DECREF(v); /* See Tktt_New() */
2747 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002748 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002749}
2750
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002751static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002752Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002753{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002754 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002755
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002756 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002757 if (v == NULL)
2758 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002759
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002760 Py_INCREF(func);
2761 v->token = NULL;
2762 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002763
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002764 /* Extra reference, deleted when called or when handler is deleted */
2765 Py_INCREF(v);
2766 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002767}
2768
2769static void
Fred Drake509d79a2000-07-08 04:04:38 +00002770Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002771{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002772 TkttObject *v = (TkttObject *)self;
2773 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002774 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002775
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002776 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002777
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002778 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002779 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002780}
2781
Guido van Rossum597ac201998-05-12 14:36:19 +00002782static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002783Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002784{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002785 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002786 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2787 v,
2788 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002789}
2790
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002791/** Timer Handler **/
2792
2793static void
Fred Drake509d79a2000-07-08 04:04:38 +00002794TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002795{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002796 TkttObject *v = (TkttObject *)clientData;
2797 PyObject *func = v->func;
2798 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002799
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002800 if (func == NULL)
2801 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002802
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002803 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002804
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002805 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002806
Victor Stinner2ff58a22019-06-17 14:27:23 +02002807 res = PyObject_CallNoArgs(func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002808 Py_DECREF(func);
2809 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002810
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002811 if (res == NULL) {
2812 errorInCmd = 1;
2813 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2814 }
2815 else
2816 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002817
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002818 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002819}
2820
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002821/*[clinic input]
2822_tkinter.tkapp.createtimerhandler
2823
2824 milliseconds: int
2825 func: object
2826 /
2827
2828[clinic start generated code]*/
2829
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002830static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002831_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2832 PyObject *func)
2833/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002834{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002835 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002837 if (!PyCallable_Check(func)) {
2838 PyErr_SetString(PyExc_TypeError, "bad argument list");
2839 return NULL;
2840 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002841
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002842 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002844 v = Tktt_New(func);
2845 if (v) {
2846 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2847 (ClientData)v);
2848 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002849
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002850 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002851}
2852
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002853
Guido van Rossum18468821994-06-20 07:49:28 +00002854/** Event Loop **/
2855
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002856/*[clinic input]
2857_tkinter.tkapp.mainloop
2858
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002859 threshold: int = 0
2860 /
2861
2862[clinic start generated code]*/
2863
Guido van Rossum18468821994-06-20 07:49:28 +00002864static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002865_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002866/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002867{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002868 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002869
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002870 CHECK_TCL_APPARTMENT;
2871 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002872
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002873 quitMainLoop = 0;
2874 while (Tk_GetNumMainWindows() > threshold &&
2875 !quitMainLoop &&
2876 !errorInCmd)
2877 {
2878 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002879
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002880 if (self->threaded) {
2881 /* Allow other Python threads to run. */
2882 ENTER_TCL
2883 result = Tcl_DoOneEvent(0);
2884 LEAVE_TCL
2885 }
2886 else {
2887 Py_BEGIN_ALLOW_THREADS
2888 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2889 tcl_tstate = tstate;
2890 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2891 tcl_tstate = NULL;
2892 if(tcl_lock)PyThread_release_lock(tcl_lock);
2893 if (result == 0)
2894 Sleep(Tkinter_busywaitinterval);
2895 Py_END_ALLOW_THREADS
2896 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002897
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002898 if (PyErr_CheckSignals() != 0) {
2899 self->dispatching = 0;
2900 return NULL;
2901 }
2902 if (result < 0)
2903 break;
2904 }
2905 self->dispatching = 0;
2906 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002907
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002908 if (errorInCmd) {
2909 errorInCmd = 0;
2910 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2911 excInCmd = valInCmd = trbInCmd = NULL;
2912 return NULL;
2913 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002914 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002915}
2916
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002917/*[clinic input]
2918_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002919
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002920 flags: int = 0
2921 /
2922
2923[clinic start generated code]*/
2924
2925static PyObject *
2926_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2927/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2928{
2929 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002930
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002931 ENTER_TCL
2932 rv = Tcl_DoOneEvent(flags);
2933 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002934 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002935}
2936
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002937/*[clinic input]
2938_tkinter.tkapp.quit
2939[clinic start generated code]*/
2940
Guido van Rossum062cfb01995-01-10 17:42:51 +00002941static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002942_tkinter_tkapp_quit_impl(TkappObject *self)
2943/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002944{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002945 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002946 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002947}
2948
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002949/*[clinic input]
2950_tkinter.tkapp.interpaddr
2951[clinic start generated code]*/
2952
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002953static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002954_tkinter_tkapp_interpaddr_impl(TkappObject *self)
2955/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002956{
Victor Stinnere1040e22013-09-05 00:22:24 +02002957 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002958}
2959
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002960/*[clinic input]
2961_tkinter.tkapp.loadtk
2962[clinic start generated code]*/
2963
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002964static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002965_tkinter_tkapp_loadtk_impl(TkappObject *self)
2966/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00002967{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002968 Tcl_Interp *interp = Tkapp_Interp(self);
2969 const char * _tk_exists = NULL;
2970 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002971
Guilherme Polob681df42009-02-09 22:33:59 +00002972#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002973 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2974 * first call failed.
2975 * To avoid the deadlock, we just refuse the second call through
2976 * a static variable.
2977 */
2978 if (tk_load_failed) {
2979 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2980 return NULL;
2981 }
Guilherme Polob681df42009-02-09 22:33:59 +00002982#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002983
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002984 /* We want to guard against calling Tk_Init() multiple times */
2985 CHECK_TCL_APPARTMENT;
2986 ENTER_TCL
2987 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2988 ENTER_OVERLAP
2989 if (err == TCL_ERROR) {
2990 /* This sets an exception, but we cannot return right
2991 away because we need to exit the overlap first. */
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002992 Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002993 } else {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03002994 _tk_exists = Tcl_GetStringResult(Tkapp_Interp(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002995 }
2996 LEAVE_OVERLAP_TCL
2997 if (err == TCL_ERROR) {
2998 return NULL;
2999 }
3000 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
3001 if (Tk_Init(interp) == TCL_ERROR) {
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +03003002 Tkinter_Error(self);
Guilherme Polob681df42009-02-09 22:33:59 +00003003#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003004 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00003005#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003006 return NULL;
3007 }
3008 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003009 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00003010}
Barry Warsawfa701a81997-01-16 00:15:11 +00003011
Martin v. Löwisffad6332002-11-26 09:28:05 +00003012static PyObject *
3013Tkapp_WantObjects(PyObject *self, PyObject *args)
3014{
3015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003016 int wantobjects = -1;
3017 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3018 return NULL;
3019 if (wantobjects == -1)
3020 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3021 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003022
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003023 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003024}
3025
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003026/*[clinic input]
3027_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003028
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003029[clinic start generated code]*/
3030
3031static PyObject *
3032_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03003033/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003034{
3035 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003036
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003037 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003038}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003039
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003040
Guido van Rossum18468821994-06-20 07:49:28 +00003041/**** Tkapp Type Methods ****/
3042
3043static void
Fred Drake509d79a2000-07-08 04:04:38 +00003044Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003045{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003046 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003047 /*CHECK_TCL_APPARTMENT;*/
3048 ENTER_TCL
3049 Tcl_DeleteInterp(Tkapp_Interp(self));
3050 LEAVE_TCL
3051 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003052 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003053 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003054}
3055
Barry Warsawfa701a81997-01-16 00:15:11 +00003056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003057
Guido van Rossum18468821994-06-20 07:49:28 +00003058/**** Tkinter Module ****/
3059
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003060typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003061 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003062 Py_ssize_t size; /* current size */
3063 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003064} FlattenContext;
3065
3066static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003067_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003068{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003069 /* expand tuple to hold (at least) size new items.
3070 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003071
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003072 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003073
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003074 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003075 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003076
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003077 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003078
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003079 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003080}
3081
3082static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003083_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003084{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003085 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003086
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003087 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003088
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003089 if (depth > 1000) {
3090 PyErr_SetString(PyExc_ValueError,
3091 "nesting too deep in _flatten");
3092 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003093 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3094 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003095 /* preallocate (assume no nesting) */
3096 if (context->size + size > context->maxsize &&
3097 !_bump(context, size))
3098 return 0;
3099 /* copy items to output tuple */
3100 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003101 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003102 if (PyList_Check(o) || PyTuple_Check(o)) {
3103 if (!_flatten1(context, o, depth + 1))
3104 return 0;
3105 } else if (o != Py_None) {
3106 if (context->size + 1 > context->maxsize &&
3107 !_bump(context, 1))
3108 return 0;
3109 Py_INCREF(o);
3110 PyTuple_SET_ITEM(context->tuple,
3111 context->size++, o);
3112 }
3113 }
3114 } else {
3115 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3116 return 0;
3117 }
3118 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003119}
3120
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003121/*[clinic input]
3122_tkinter._flatten
3123
3124 item: object
3125 /
3126
3127[clinic start generated code]*/
3128
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003129static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003130_tkinter__flatten(PyObject *module, PyObject *item)
3131/*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003132{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003133 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003134
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003135 context.maxsize = PySequence_Size(item);
3136 if (context.maxsize < 0)
3137 return NULL;
3138 if (context.maxsize == 0)
3139 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003141 context.tuple = PyTuple_New(context.maxsize);
3142 if (!context.tuple)
3143 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003144
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003145 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003146
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003147 if (!_flatten1(&context, item,0))
3148 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003149
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003150 if (_PyTuple_Resize(&context.tuple, context.size))
3151 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003152
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003153 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003154}
3155
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003156/*[clinic input]
3157_tkinter.create
3158
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003159 screenName: str(accept={str, NoneType}) = None
3160 baseName: str = ""
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003161 className: str = "Tk"
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003162 interactive: bool(accept={int}) = False
3163 wantobjects: bool(accept={int}) = False
3164 wantTk: bool(accept={int}) = True
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003165 if false, then Tk_Init() doesn't get called
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003166 sync: bool(accept={int}) = False
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003167 if true, then pass -sync to wish
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003168 use: str(accept={str, NoneType}) = None
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003169 if not None, then pass -use to wish
3170 /
3171
3172[clinic start generated code]*/
3173
Guido van Rossum18468821994-06-20 07:49:28 +00003174static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003175_tkinter_create_impl(PyObject *module, const char *screenName,
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003176 const char *baseName, const char *className,
3177 int interactive, int wantobjects, int wantTk, int sync,
3178 const char *use)
Serhiy Storchaka279f4462019-09-14 12:24:05 +03003179/*[clinic end generated code: output=e3315607648e6bb4 input=da9b17ee7358d862]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003180{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003181 /* XXX baseName is not used anymore;
3182 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003183 CHECK_STRING_LENGTH(screenName);
3184 CHECK_STRING_LENGTH(baseName);
3185 CHECK_STRING_LENGTH(className);
3186 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003187
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003188 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003189 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003190 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003191}
3192
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003193/*[clinic input]
3194_tkinter.setbusywaitinterval
3195
3196 new_val: int
3197 /
3198
3199Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3200
3201It should be set to a divisor of the maximum time between frames in an animation.
3202[clinic start generated code]*/
3203
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003204static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003205_tkinter_setbusywaitinterval_impl(PyObject *module, int new_val)
3206/*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003207{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003208 if (new_val < 0) {
3209 PyErr_SetString(PyExc_ValueError,
3210 "busywaitinterval must be >= 0");
3211 return NULL;
3212 }
3213 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003214 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003215}
3216
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003217/*[clinic input]
3218_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003219
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003220Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3221[clinic start generated code]*/
3222
3223static int
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003224_tkinter_getbusywaitinterval_impl(PyObject *module)
3225/*[clinic end generated code: output=23b72d552001f5c7 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003226{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003227 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003228}
3229
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003230#include "clinic/_tkinter.c.h"
3231
3232static PyMethodDef Tktt_methods[] =
3233{
3234 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3235 {NULL, NULL}
3236};
3237
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003238static PyType_Slot Tktt_Type_slots[] = {
3239 {Py_tp_dealloc, Tktt_Dealloc},
3240 {Py_tp_repr, Tktt_Repr},
3241 {Py_tp_methods, Tktt_methods},
3242 {0, 0}
3243};
3244
3245static PyType_Spec Tktt_Type_spec = {
3246 "_tkinter.tktimertoken",
3247 sizeof(TkttObject),
3248 0,
3249 Py_TPFLAGS_DEFAULT,
3250 Tktt_Type_slots,
3251};
3252
3253
3254/**** Tkapp Method List ****/
3255
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003256static PyMethodDef Tkapp_methods[] =
3257{
3258 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3259 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3260 {"call", Tkapp_Call, METH_VARARGS},
3261 _TKINTER_TKAPP_EVAL_METHODDEF
3262 _TKINTER_TKAPP_EVALFILE_METHODDEF
3263 _TKINTER_TKAPP_RECORD_METHODDEF
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03003264 _TKINTER_TKAPP_ADDERRORINFO_METHODDEF
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003265 {"setvar", Tkapp_SetVar, METH_VARARGS},
3266 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3267 {"getvar", Tkapp_GetVar, METH_VARARGS},
3268 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3269 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3270 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3271 _TKINTER_TKAPP_GETINT_METHODDEF
3272 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3273 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3274 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3275 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3276 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3277 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3278 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3279 _TKINTER_TKAPP_SPLIT_METHODDEF
3280 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3281 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3282 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3283 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3284 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3285 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3286 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3287 _TKINTER_TKAPP_QUIT_METHODDEF
3288 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3289 _TKINTER_TKAPP_LOADTK_METHODDEF
3290 {NULL, NULL}
3291};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003292
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003293static PyType_Slot Tkapp_Type_slots[] = {
3294 {Py_tp_dealloc, Tkapp_Dealloc},
3295 {Py_tp_methods, Tkapp_methods},
3296 {0, 0}
3297};
3298
3299
3300static PyType_Spec Tkapp_Type_spec = {
3301 "_tkinter.tkapp",
3302 sizeof(TkappObject),
3303 0,
3304 Py_TPFLAGS_DEFAULT,
3305 Tkapp_Type_slots,
3306};
3307
Guido van Rossum18468821994-06-20 07:49:28 +00003308static PyMethodDef moduleMethods[] =
3309{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003310 _TKINTER__FLATTEN_METHODDEF
3311 _TKINTER_CREATE_METHODDEF
3312 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3313 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003314 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003315};
3316
Guido van Rossum7bf15641998-05-22 18:28:17 +00003317#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003318
3319static int stdin_ready = 0;
3320
Guido van Rossumad4db171998-06-13 13:56:28 +00003321#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003322static void
Fred Drake509d79a2000-07-08 04:04:38 +00003323MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003324{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003325 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003326}
Guido van Rossumad4db171998-06-13 13:56:28 +00003327#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003328
Guido van Rossum00d93061998-05-28 23:06:38 +00003329static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003330
Guido van Rossum18468821994-06-20 07:49:28 +00003331static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003332EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003333{
Guido van Rossumad4db171998-06-13 13:56:28 +00003334#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003335 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003336#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003337 PyEval_RestoreThread(event_tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003338 stdin_ready = 0;
3339 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003340#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003341 tfile = fileno(stdin);
3342 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003343#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003344 while (!errorInCmd && !stdin_ready) {
3345 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003346#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003347 if (_kbhit()) {
3348 stdin_ready = 1;
3349 break;
3350 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003351#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003352 Py_BEGIN_ALLOW_THREADS
3353 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3354 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003356 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003357
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003358 tcl_tstate = NULL;
3359 if(tcl_lock)PyThread_release_lock(tcl_lock);
3360 if (result == 0)
3361 Sleep(Tkinter_busywaitinterval);
3362 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003364 if (result < 0)
3365 break;
3366 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003367#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003368 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003369#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003370 if (errorInCmd) {
3371 errorInCmd = 0;
3372 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3373 excInCmd = valInCmd = trbInCmd = NULL;
3374 PyErr_Print();
3375 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003376 PyEval_SaveThread();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003377 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003378}
Guido van Rossum18468821994-06-20 07:49:28 +00003379
Guido van Rossum00d93061998-05-28 23:06:38 +00003380#endif
3381
Guido van Rossum7bf15641998-05-22 18:28:17 +00003382static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003383EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003384{
Guido van Rossum00d93061998-05-28 23:06:38 +00003385#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003386 if (PyOS_InputHook == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003387 event_tstate = PyThreadState_Get();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003388 PyOS_InputHook = EventHook;
3389 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003390#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003391}
3392
3393static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003394DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003395{
Guido van Rossum00d93061998-05-28 23:06:38 +00003396#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003397 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3398 PyOS_InputHook = NULL;
3399 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003400#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003401}
3402
Barry Warsawfa701a81997-01-16 00:15:11 +00003403
Martin v. Löwis1a214512008-06-11 05:26:20 +00003404static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003405 PyModuleDef_HEAD_INIT,
3406 "_tkinter",
3407 NULL,
3408 -1,
3409 moduleMethods,
3410 NULL,
3411 NULL,
3412 NULL,
3413 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003414};
3415
Mark Hammond62b1ab12002-07-23 06:31:15 +00003416PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003417PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003418{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003419 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003421 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003422 if (tcl_lock == NULL)
3423 return NULL;
Guido van Rossumae92f011996-08-21 19:03:36 +00003424
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003425 m = PyModule_Create(&_tkintermodule);
3426 if (m == NULL)
3427 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003428
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003429 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3430 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003431 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003432 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003433 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003434 Py_INCREF(o);
3435 if (PyModule_AddObject(m, "TclError", o)) {
3436 Py_DECREF(o);
3437 Py_DECREF(m);
3438 return NULL;
3439 }
3440 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003441
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003442 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3443 Py_DECREF(m);
3444 return NULL;
3445 }
3446 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3447 Py_DECREF(m);
3448 return NULL;
3449 }
3450 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3451 Py_DECREF(m);
3452 return NULL;
3453 }
3454 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3455 Py_DECREF(m);
3456 return NULL;
3457 }
3458 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3459 Py_DECREF(m);
3460 return NULL;
3461 }
3462 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3463 Py_DECREF(m);
3464 return NULL;
3465 }
3466 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3467 Py_DECREF(m);
3468 return NULL;
3469 }
3470 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3471 Py_DECREF(m);
3472 return NULL;
3473 }
3474 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3475 Py_DECREF(m);
3476 return NULL;
3477 }
3478 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3479 Py_DECREF(m);
3480 return NULL;
3481 }
3482 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3483 Py_DECREF(m);
3484 return NULL;
3485 }
3486
3487 o = PyType_FromSpec(&Tkapp_Type_spec);
3488 if (o == NULL) {
3489 Py_DECREF(m);
3490 return NULL;
3491 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003492 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003493 if (PyModule_AddObject(m, "TkappType", o)) {
3494 Py_DECREF(o);
3495 Py_DECREF(m);
3496 return NULL;
3497 }
3498 Tkapp_Type = o;
3499
3500 o = PyType_FromSpec(&Tktt_Type_spec);
3501 if (o == NULL) {
3502 Py_DECREF(m);
3503 return NULL;
3504 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003505 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003506 if (PyModule_AddObject(m, "TkttType", o)) {
3507 Py_DECREF(o);
3508 Py_DECREF(m);
3509 return NULL;
3510 }
3511 Tktt_Type = o;
3512
3513 o = PyType_FromSpec(&PyTclObject_Type_spec);
3514 if (o == NULL) {
3515 Py_DECREF(m);
3516 return NULL;
3517 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003518 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003519 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3520 Py_DECREF(o);
3521 Py_DECREF(m);
3522 return NULL;
3523 }
3524 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003525
3526#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003527 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3528 * start waking up. Note that Tcl_FindExecutable will do this, this
3529 * code must be above it! The original warning from
3530 * tkMacOSXAppInit.c is copied below.
3531 *
3532 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3533 * Tcl interpreter for now. It probably should work to do this
3534 * in the other order, but for now it doesn't seem to.
3535 *
3536 */
3537 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003538#endif
3539
3540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003541 /* This helps the dynamic loader; in Unicode aware Tcl versions
3542 it also helps Tcl find its encodings. */
3543 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3544 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003545 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003546 if (cexe) {
3547#ifdef MS_WINDOWS
3548 int set_var = 0;
3549 PyObject *str_path;
3550 wchar_t *wcs_path;
3551 DWORD ret;
3552
3553 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3554
3555 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3556 str_path = _get_tcl_lib_path();
3557 if (str_path == NULL && PyErr_Occurred()) {
3558 return NULL;
3559 }
3560 if (str_path != NULL) {
3561 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3562 if (wcs_path == NULL) {
3563 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}