blob: a96924c9c6e71ddc581fca0f4f509585024da141 [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
Guido van Rossumad4db171998-06-13 13:56:28 +000099#ifdef MS_WINDOWS
100#include <conio.h>
101#define WAIT_FOR_STDIN
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500102
103static PyObject *
104_get_tcl_lib_path()
105{
106 static PyObject *tcl_library_path = NULL;
107 static int already_checked = 0;
108
109 if (already_checked == 0) {
110 PyObject *prefix;
111 struct stat stat_buf;
112 int stat_return_value;
113
114 prefix = PyUnicode_FromWideChar(Py_GetPrefix(), -1);
115 if (prefix == NULL) {
116 return NULL;
117 }
118
119 /* Check expected location for an installed Python first */
120 tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION);
121 if (tcl_library_path == NULL) {
122 return NULL;
123 }
124 tcl_library_path = PyUnicode_Concat(prefix, tcl_library_path);
125 if (tcl_library_path == NULL) {
126 return NULL;
127 }
128 stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
129 if (stat_return_value == -2) {
130 return NULL;
131 }
132 if (stat_return_value == -1) {
133 /* install location doesn't exist, reset errno and see if
134 we're a repository build */
135 errno = 0;
136#ifdef Py_TCLTK_DIR
137 tcl_library_path = PyUnicode_FromString(
138 Py_TCLTK_DIR "\\lib\\tcl" TCL_VERSION);
139 if (tcl_library_path == NULL) {
140 return NULL;
141 }
142 stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
143 if (stat_return_value == -2) {
144 return NULL;
145 }
146 if (stat_return_value == -1) {
147 /* tcltkDir for a repository build doesn't exist either,
148 reset errno and leave Tcl to its own devices */
149 errno = 0;
150 tcl_library_path = NULL;
151 }
152#else
153 tcl_library_path = NULL;
Guido van Rossumad4db171998-06-13 13:56:28 +0000154#endif
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500155 }
156 already_checked = 1;
157 }
158 return tcl_library_path;
159}
160#endif /* MS_WINDOWS */
Guido van Rossumad4db171998-06-13 13:56:28 +0000161
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000162/* The threading situation is complicated. Tcl is not thread-safe, except
163 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000164
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300165 So we need to use a lock around all uses of Tcl. Previously, the
166 Python interpreter lock was used for this. However, this causes
167 problems when other Python threads need to run while Tcl is blocked
168 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000169
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300170 To solve this problem, a separate lock for Tcl is introduced.
171 Holding it is incompatible with holding Python's interpreter lock.
172 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000173
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300174 ENTER_TCL and LEAVE_TCL are brackets, just like
175 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
176 used whenever a call into Tcl is made that could call an event
177 handler, or otherwise affect the state of a Tcl interpreter. These
178 assume that the surrounding code has the Python interpreter lock;
179 inside the brackets, the Python interpreter lock has been released
180 and the lock for Tcl has been acquired.
181
182 Sometimes, it is necessary to have both the Python lock and the Tcl
183 lock. (For example, when transferring data from the Tcl
184 interpreter result to a Python string object.) This can be done by
185 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
186 reacquires the Python lock (and restores the thread state) but
187 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
188 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000189
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000190 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300191 handlers when the handler needs to use Python. Such event handlers
192 are entered while the lock for Tcl is held; the event handler
193 presumably needs to use Python. ENTER_PYTHON releases the lock for
194 Tcl and acquires the Python interpreter lock, restoring the
195 appropriate thread state, and LEAVE_PYTHON releases the Python
196 interpreter lock and re-acquires the lock for Tcl. It is okay for
197 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
198 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000199
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300200 These locks expand to several statements and brackets; they should
201 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300203 If Tcl is threaded, this approach won't work anymore. The Tcl
204 interpreter is only valid in the thread that created it, and all Tk
205 activity must happen in this thread, also. That means that the
206 mainloop must be invoked in the thread that created the
207 interpreter. Invoking commands from other threads is possible;
208 _tkinter will queue an event for the interpreter thread, which will
209 then execute the command and pass back the result. If the main
210 thread is not in the mainloop, and invoking commands causes an
211 exception; if the main loop is running but not processing events,
212 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000213
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300214 In addition, for a threaded Tcl, a single global tcl_tstate won't
215 be sufficient anymore, since multiple Tcl interpreters may
216 simultaneously dispatch in different threads. So we use the Tcl TLS
217 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000218
Guido van Rossum00d93061998-05-28 23:06:38 +0000219*/
220
Guido van Rossum65d5b571998-12-21 19:32:43 +0000221static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000222
223#ifdef TCL_THREADS
224static Tcl_ThreadDataKey state_key;
225typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300226#define tcl_tstate \
227 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000228#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000229static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000230#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000231
232#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000233 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
234 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000235
236#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300237 tcl_tstate = NULL; \
238 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000239
Guido van Rossum62320c91998-06-15 04:36:09 +0000240#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000241 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000242
243#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000244 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000245
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000246#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000247 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300248 if(tcl_lock) \
249 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000250
251#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000252 { PyThreadState *tstate = PyEval_SaveThread(); \
253 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000254
255#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000256 if (((TkappObject *)self)->threaded && \
257 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300258 PyErr_SetString(PyExc_RuntimeError, \
luzpaza5293b42017-11-05 07:37:50 -0600259 "Calling Tcl from different apartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 return 0; \
261 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000262
Guido van Rossum97867b21996-08-08 19:09:53 +0000263#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000264#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000265#endif
266
Guido van Rossum18468821994-06-20 07:49:28 +0000267/**** Tkapp Object Declaration ****/
268
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300269static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000270
Guido van Rossum00d93061998-05-28 23:06:38 +0000271typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000272 PyObject_HEAD
273 Tcl_Interp *interp;
274 int wantobjects;
275 int threaded; /* True if tcl_platform[threaded] */
276 Tcl_ThreadId thread_id;
277 int dispatching;
278 /* We cannot include tclInt.h, as this is internal.
279 So we cache interesting types here. */
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200280 const Tcl_ObjType *OldBooleanType;
Zachary Ware037605b2014-08-05 11:54:34 -0500281 const Tcl_ObjType *BooleanType;
282 const Tcl_ObjType *ByteArrayType;
283 const Tcl_ObjType *DoubleType;
284 const Tcl_ObjType *IntType;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300285 const Tcl_ObjType *WideIntType;
286 const Tcl_ObjType *BignumType;
Zachary Ware037605b2014-08-05 11:54:34 -0500287 const Tcl_ObjType *ListType;
288 const Tcl_ObjType *ProcBodyType;
289 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000290} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000291
Guido van Rossum18468821994-06-20 07:49:28 +0000292#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000293#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000294
Guido van Rossum35d43371997-08-02 00:09:09 +0000295#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000296(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000297
Barry Warsawfa701a81997-01-16 00:15:11 +0000298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000299
Guido van Rossum18468821994-06-20 07:49:28 +0000300/**** Error Handling ****/
301
302static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000303static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000304static int errorInCmd = 0;
305static PyObject *excInCmd;
306static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000307static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000308
Guilherme Polob681df42009-02-09 22:33:59 +0000309#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000310static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000311#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000313
Guido van Rossum18468821994-06-20 07:49:28 +0000314static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000315Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000316{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000317 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
318 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000319}
320
Barry Warsawfa701a81997-01-16 00:15:11 +0000321
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000322
Guido van Rossum18468821994-06-20 07:49:28 +0000323/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000324
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000325static int Tkinter_busywaitinterval = 20;
326
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000327#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000328
Guido van Rossum00d93061998-05-28 23:06:38 +0000329/* Millisecond sleep() for Unix platforms. */
330
331static void
Fred Drake509d79a2000-07-08 04:04:38 +0000332Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000333{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334 /* XXX Too bad if you don't have select(). */
335 struct timeval t;
336 t.tv_sec = milli/1000;
337 t.tv_usec = (milli%1000) * 1000;
338 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000339}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000340#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000341
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000342/* Wait up to 1s for the mainloop to come up. */
343
344static int
345WaitForMainloop(TkappObject* self)
346{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000347 int i;
348 for (i = 0; i < 10; i++) {
349 if (self->dispatching)
350 return 1;
351 Py_BEGIN_ALLOW_THREADS
352 Sleep(100);
353 Py_END_ALLOW_THREADS
354 }
355 if (self->dispatching)
356 return 1;
357 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
358 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000359}
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362
Guido van Rossum18468821994-06-20 07:49:28 +0000363#define ARGSZ 64
364
Barry Warsawfa701a81997-01-16 00:15:11 +0000365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000366
Guido van Rossum18468821994-06-20 07:49:28 +0000367static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200368unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
369{
370 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
371 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
372 /* Tcl encodes null character as \xc0\x80 */
373 if (memchr(s, '\xc0', size)) {
374 char *buf, *q;
375 const char *e = s + size;
376 PyErr_Clear();
377 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300378 if (buf == NULL) {
379 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200380 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300381 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200382 while (s != e) {
383 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
384 *q++ = '\0';
385 s += 2;
386 }
387 else
388 *q++ = *s++;
389 }
390 s = buf;
391 size = q - s;
392 r = PyUnicode_DecodeUTF8(s, size, NULL);
393 PyMem_Free(buf);
394 }
395 }
396 return r;
397}
398
399static PyObject *
400unicodeFromTclString(const char *s)
401{
402 return unicodeFromTclStringAndSize(s, strlen(s));
403}
404
405static PyObject *
406unicodeFromTclObj(Tcl_Obj *value)
407{
408 int len;
409 char *s = Tcl_GetStringFromObj(value, &len);
410 return unicodeFromTclStringAndSize(s, len);
411}
412
413
414static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300415Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000416{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000417 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300418 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000419 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000421 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300422 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 }
Guido van Rossum18468821994-06-20 07:49:28 +0000424
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000425 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
426 /* Not a list.
427 * Could be a quoted string containing funnies, e.g. {"}.
428 * Return the string itself.
429 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200430 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000431 }
Guido van Rossum18468821994-06-20 07:49:28 +0000432
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000433 if (argc == 0)
434 v = PyUnicode_FromString("");
435 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200436 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000437 else if ((v = PyTuple_New(argc)) != NULL) {
438 int i;
439 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000441 for (i = 0; i < argc; i++) {
442 if ((w = Split(argv[i])) == NULL) {
443 Py_DECREF(v);
444 v = NULL;
445 break;
446 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300447 PyTuple_SET_ITEM(v, i, w);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000448 }
449 }
450 Tcl_Free(FREECAST argv);
451 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000452}
453
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300454/* In some cases, Tcl will still return strings that are supposed to
455 be lists. SplitObj walks through a nested tuple, finding string
456 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000457
Martin v. Löwis59683e82008-06-13 07:50:45 +0000458static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000459SplitObj(PyObject *arg)
460{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 if (PyTuple_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200462 Py_ssize_t i, size;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000463 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000464
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300465 size = PyTuple_GET_SIZE(arg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 result = NULL;
467 /* Recursively invoke SplitObj for all tuple items.
468 If this does not return a new object, no action is
469 needed. */
470 for(i = 0; i < size; i++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300471 elem = PyTuple_GET_ITEM(arg, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000472 newelem = SplitObj(elem);
473 if (!newelem) {
474 Py_XDECREF(result);
475 return NULL;
476 }
477 if (!result) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200478 Py_ssize_t k;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000479 if (newelem == elem) {
480 Py_DECREF(newelem);
481 continue;
482 }
483 result = PyTuple_New(size);
484 if (!result)
485 return NULL;
486 for(k = 0; k < i; k++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300487 elem = PyTuple_GET_ITEM(arg, k);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000488 Py_INCREF(elem);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300489 PyTuple_SET_ITEM(result, k, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 }
491 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300492 PyTuple_SET_ITEM(result, i, newelem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000493 }
494 if (result)
495 return result;
496 /* Fall through, returning arg. */
497 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300498 else if (PyList_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200499 Py_ssize_t i, size;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300500 PyObject *elem, *newelem, *result;
501
502 size = PyList_GET_SIZE(arg);
503 result = PyTuple_New(size);
504 if (!result)
505 return NULL;
506 /* Recursively invoke SplitObj for all list items. */
507 for(i = 0; i < size; i++) {
508 elem = PyList_GET_ITEM(arg, i);
509 newelem = SplitObj(elem);
510 if (!newelem) {
511 Py_XDECREF(result);
512 return NULL;
513 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300514 PyTuple_SET_ITEM(result, i, newelem);
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300515 }
516 return result;
517 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300518 else if (PyUnicode_Check(arg)) {
519 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300520 const char **argv;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200521 const char *list = PyUnicode_AsUTF8(arg);
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300522
523 if (list == NULL ||
524 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
525 Py_INCREF(arg);
526 return arg;
527 }
528 Tcl_Free(FREECAST argv);
529 if (argc > 1)
530 return Split(list);
531 /* Fall through, returning arg. */
532 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 else if (PyBytes_Check(arg)) {
534 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300535 const char **argv;
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300536 char *list = PyBytes_AS_STRING(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000537
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000538 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
539 Py_INCREF(arg);
540 return arg;
541 }
542 Tcl_Free(FREECAST argv);
543 if (argc > 1)
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300544 return Split(PyBytes_AS_STRING(arg));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000545 /* Fall through, returning arg. */
546 }
547 Py_INCREF(arg);
548 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000549}
Barry Warsawfa701a81997-01-16 00:15:11 +0000550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +0300552/*[clinic input]
553module _tkinter
554class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec"
555class _tkinter.Tcl_Obj "PyTclObject *" "&PyTclObject_Type_spec"
556class _tkinter.tktimertoken "TkttObject *" "&Tktt_Type_spec"
557[clinic start generated code]*/
558/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b1ebf15c162ee229]*/
559
Guido van Rossum18468821994-06-20 07:49:28 +0000560/**** Tkapp Object ****/
561
562#ifndef WITH_APPINIT
563int
Fred Drake509d79a2000-07-08 04:04:38 +0000564Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000565{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000566 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000567
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000568 if (Tcl_Init(interp) == TCL_ERROR) {
569 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
570 return TCL_ERROR;
571 }
Guilherme Polob681df42009-02-09 22:33:59 +0000572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000573 _tkinter_skip_tk_init = Tcl_GetVar(interp,
574 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
575 if (_tkinter_skip_tk_init != NULL &&
576 strcmp(_tkinter_skip_tk_init, "1") == 0) {
577 return TCL_OK;
578 }
Guilherme Polob681df42009-02-09 22:33:59 +0000579
580#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000581 if (tk_load_failed) {
582 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
583 return TCL_ERROR;
584 }
Guilherme Polob681df42009-02-09 22:33:59 +0000585#endif
586
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000587 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000588#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000589 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000590#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
592 return TCL_ERROR;
593 }
Guilherme Polob681df42009-02-09 22:33:59 +0000594
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000595 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000596}
597#endif /* !WITH_APPINIT */
598
Guido van Rossum18468821994-06-20 07:49:28 +0000599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000600
Barry Warsawfa701a81997-01-16 00:15:11 +0000601
602/* Initialize the Tk application; see the `main' function in
603 * `tkMain.c'.
604 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000605
Thomas Wouters58d05102000-07-24 14:43:35 +0000606static void EnableEventHook(void); /* Forward */
607static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000608
Barry Warsawfa701a81997-01-16 00:15:11 +0000609static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300610Tkapp_New(const char *screenName, const char *className,
611 int interactive, int wantobjects, int wantTk, int sync,
612 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000613{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 TkappObject *v;
615 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000616
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300617 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 if (v == NULL)
619 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200620 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000621
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000622 v->interp = Tcl_CreateInterp();
623 v->wantobjects = wantobjects;
624 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
625 TCL_GLOBAL_ONLY) != NULL;
626 v->thread_id = Tcl_GetCurrentThread();
627 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000628
629#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300631 PyErr_SetString(PyExc_RuntimeError,
632 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 Py_DECREF(v);
634 return 0;
635 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000636#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 if (v->threaded && tcl_lock) {
638 /* If Tcl is threaded, we don't need the lock. */
639 PyThread_free_lock(tcl_lock);
640 tcl_lock = NULL;
641 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000642
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200643 v->OldBooleanType = Tcl_GetObjType("boolean");
644 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 v->ByteArrayType = Tcl_GetObjType("bytearray");
646 v->DoubleType = Tcl_GetObjType("double");
647 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300648 v->WideIntType = Tcl_GetObjType("wideInt");
649 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 v->ListType = Tcl_GetObjType("list");
651 v->ProcBodyType = Tcl_GetObjType("procbody");
652 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 /* Delete the 'exit' command, which can screw things up */
655 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000656
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000657 if (screenName != NULL)
658 Tcl_SetVar2(v->interp, "env", "DISPLAY",
659 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 if (interactive)
662 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
663 else
664 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200667 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 if (!argv0) {
669 PyErr_NoMemory();
670 Py_DECREF(v);
671 return NULL;
672 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200675 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
676 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200678 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000679
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000680 if (! wantTk) {
681 Tcl_SetVar(v->interp,
682 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
683 }
Guilherme Polob681df42009-02-09 22:33:59 +0000684#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 else if (tk_load_failed) {
686 Tcl_SetVar(v->interp,
687 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
688 }
Guilherme Polob681df42009-02-09 22:33:59 +0000689#endif
David Aschere2b4b322004-02-18 05:59:53 +0000690
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 /* some initial arguments need to be in argv */
692 if (sync || use) {
693 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200694 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000696 if (sync)
697 len += sizeof "-sync";
698 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200699 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000700
Victor Stinneree6c3c72014-09-11 17:50:21 +0200701 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 if (!args) {
703 PyErr_NoMemory();
704 Py_DECREF(v);
705 return NULL;
706 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000707
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000708 args[0] = '\0';
709 if (sync)
710 strcat(args, "-sync");
711 if (use) {
712 if (sync)
713 strcat(args, " ");
714 strcat(args, "-use ");
715 strcat(args, use);
716 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200719 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000721
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500722#ifdef MS_WINDOWS
723 {
724 PyObject *str_path;
725 PyObject *utf8_path;
726 DWORD ret;
727
728 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
729 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
730 str_path = _get_tcl_lib_path();
731 if (str_path == NULL && PyErr_Occurred()) {
732 return NULL;
733 }
734 if (str_path != NULL) {
735 utf8_path = PyUnicode_AsUTF8String(str_path);
736 if (utf8_path == NULL) {
737 return NULL;
738 }
739 Tcl_SetVar(v->interp,
740 "tcl_library",
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300741 PyBytes_AS_STRING(utf8_path),
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500742 TCL_GLOBAL_ONLY);
743 Py_DECREF(utf8_path);
744 }
745 }
746 }
747#endif
748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 if (Tcl_AppInit(v->interp) != TCL_OK) {
750 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000751#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752 if (wantTk) {
753 const char *_tkinter_tk_failed;
754 _tkinter_tk_failed = Tcl_GetVar(v->interp,
755 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000756
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000757 if ( _tkinter_tk_failed != NULL &&
758 strcmp(_tkinter_tk_failed, "1") == 0) {
759 tk_load_failed = 1;
760 }
761 }
Guilherme Polob681df42009-02-09 22:33:59 +0000762#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000763 Py_DECREF((PyObject *)v);
764 return (TkappObject *)result;
765 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000766
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000767 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000770}
771
Barry Warsawfa701a81997-01-16 00:15:11 +0000772
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000773static void
774Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000776{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000777 Py_BEGIN_ALLOW_THREADS;
778 Tcl_MutexLock(mutex);
779 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
780 Tcl_ThreadAlert(self->thread_id);
781 Tcl_ConditionWait(cond, mutex, NULL);
782 Tcl_MutexUnlock(mutex);
783 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000784}
785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000786
Guido van Rossum18468821994-06-20 07:49:28 +0000787/** Tcl Eval **/
788
Martin v. Löwisffad6332002-11-26 09:28:05 +0000789typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000790 PyObject_HEAD
791 Tcl_Obj *value;
792 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000793} PyTclObject;
794
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300795static PyObject *PyTclObject_Type;
796#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000797
798static PyObject *
799newPyTclObject(Tcl_Obj *arg)
800{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000801 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300802 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000803 if (self == NULL)
804 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200805 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000806 Tcl_IncrRefCount(arg);
807 self->value = arg;
808 self->string = NULL;
809 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000810}
811
812static void
813PyTclObject_dealloc(PyTclObject *self)
814{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200815 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000816 Tcl_DecrRefCount(self->value);
817 Py_XDECREF(self->string);
818 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200819 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000820}
821
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200822static const char *
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000823PyTclObject_TclString(PyObject *self)
824{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000825 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000826}
827
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000828/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000829PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000830"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000831
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000832static PyObject *
833PyTclObject_string(PyTclObject *self, void *ignored)
834{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000835 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200836 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000837 if (!self->string)
838 return NULL;
839 }
840 Py_INCREF(self->string);
841 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000842}
843
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000844static PyObject *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -0800845PyTclObject_str(PyTclObject *self)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000846{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200847 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000848 Py_INCREF(self->string);
849 return self->string;
850 }
851 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200852 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000853}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000854
Martin v. Löwisffad6332002-11-26 09:28:05 +0000855static PyObject *
856PyTclObject_repr(PyTclObject *self)
857{
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -0800858 PyObject *repr, *str = PyTclObject_str(self);
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300859 if (str == NULL)
860 return NULL;
861 repr = PyUnicode_FromFormat("<%s object: %R>",
862 self->value->typePtr->name, str);
863 Py_DECREF(str);
864 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000865}
866
Mark Dickinson211c6252009-02-01 10:28:51 +0000867static PyObject *
868PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000869{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000870 int result;
Mark Dickinson211c6252009-02-01 10:28:51 +0000871
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000872 /* neither argument should be NULL, unless something's gone wrong */
873 if (self == NULL || other == NULL) {
874 PyErr_BadInternalCall();
875 return NULL;
876 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000877
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000878 /* both arguments should be instances of PyTclObject */
879 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
stratakise8b19652017-11-02 11:32:54 +0100880 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000882
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000883 if (self == other)
884 /* fast path when self and other are identical */
885 result = 0;
886 else
887 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
888 Tcl_GetString(((PyTclObject *)other)->value));
stratakise8b19652017-11-02 11:32:54 +0100889 Py_RETURN_RICHCOMPARE(result, 0, op);
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000890}
891
Martin v. Löwis39195712003-01-04 00:33:13 +0000892PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
893
Martin v. Löwisffad6332002-11-26 09:28:05 +0000894static PyObject*
895get_typename(PyTclObject* obj, void* ignored)
896{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200897 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000898}
899
Martin v. Löwis39195712003-01-04 00:33:13 +0000900
Martin v. Löwisffad6332002-11-26 09:28:05 +0000901static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000902 {"typename", (getter)get_typename, NULL, get_typename__doc__},
903 {"string", (getter)PyTclObject_string, NULL,
904 PyTclObject_string__doc__},
905 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000906};
907
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300908static PyType_Slot PyTclObject_Type_slots[] = {
909 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
910 {Py_tp_repr, (reprfunc)PyTclObject_repr},
911 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200912 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300913 {Py_tp_richcompare, PyTclObject_richcompare},
914 {Py_tp_getset, PyTclObject_getsetlist},
915 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000916};
917
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300918static PyType_Spec PyTclObject_Type_spec = {
919 "_tkinter.Tcl_Obj",
920 sizeof(PyTclObject),
921 0,
922 Py_TPFLAGS_DEFAULT,
923 PyTclObject_Type_slots,
924};
925
926
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700927#if SIZE_MAX > INT_MAX
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300928#define CHECK_STRING_LENGTH(s) do { \
929 if (s != NULL && strlen(s) >= INT_MAX) { \
930 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
931 return NULL; \
932 } } while(0)
933#else
934#define CHECK_STRING_LENGTH(s)
935#endif
936
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300937#ifdef HAVE_LIBTOMMAMTH
938static Tcl_Obj*
939asBignumObj(PyObject *value)
940{
941 Tcl_Obj *result;
942 int neg;
943 PyObject *hexstr;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200944 const char *hexchars;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300945 mp_int bigValue;
946
947 neg = Py_SIZE(value) < 0;
948 hexstr = _PyLong_Format(value, 16);
949 if (hexstr == NULL)
950 return NULL;
951 hexchars = PyUnicode_AsUTF8(hexstr);
952 if (hexchars == NULL) {
953 Py_DECREF(hexstr);
954 return NULL;
955 }
956 hexchars += neg + 2; /* skip sign and "0x" */
957 mp_init(&bigValue);
958 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
959 mp_clear(&bigValue);
960 Py_DECREF(hexstr);
961 PyErr_NoMemory();
962 return NULL;
963 }
964 Py_DECREF(hexstr);
965 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
966 result = Tcl_NewBignumObj(&bigValue);
967 mp_clear(&bigValue);
968 if (result == NULL) {
969 PyErr_NoMemory();
970 return NULL;
971 }
972 return result;
973}
974#endif
975
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000976static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000977AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000978{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000979 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000980
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200981 if (PyBytes_Check(value)) {
982 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
983 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
984 return NULL;
985 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300986 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200987 (int)PyBytes_GET_SIZE(value));
988 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300989
990 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000991 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300992
993 if (PyLong_CheckExact(value)) {
994 int overflow;
995 long longValue;
996#ifdef TCL_WIDE_INT_TYPE
997 Tcl_WideInt wideValue;
998#endif
999 longValue = PyLong_AsLongAndOverflow(value, &overflow);
1000 if (!overflow) {
1001 return Tcl_NewLongObj(longValue);
1002 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001003 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001004 fall through to wideInt handling. */
1005#ifdef TCL_WIDE_INT_TYPE
1006 if (_PyLong_AsByteArray((PyLongObject *)value,
1007 (unsigned char *)(void *)&wideValue,
1008 sizeof(wideValue),
1009 PY_LITTLE_ENDIAN,
1010 /* signed */ 1) == 0) {
1011 return Tcl_NewWideIntObj(wideValue);
1012 }
1013 PyErr_Clear();
1014#endif
1015 /* If there is an overflow in the wideInt conversion,
1016 fall through to bignum handling. */
1017#ifdef HAVE_LIBTOMMAMTH
1018 return asBignumObj(value);
1019#endif
1020 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001021 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001022 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001023
1024 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001025 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001026
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +03001027 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001028 Tcl_Obj **argv;
1029 Py_ssize_t size, i;
1030
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001031 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001032 if (size == 0)
1033 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001034 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001035 PyErr_SetString(PyExc_OverflowError,
1036 PyTuple_Check(value) ? "tuple is too long" :
1037 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001038 return NULL;
1039 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001040 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
1041 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001042 PyErr_NoMemory();
1043 return NULL;
1044 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001045 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001046 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001047 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001048 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001049 return result;
1050 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001051
1052 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001053 void *inbuf;
1054 Py_ssize_t size;
1055 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001056 Tcl_UniChar *outbuf = NULL;
1057 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001058 size_t allocsize;
1059
1060 if (PyUnicode_READY(value) == -1)
1061 return NULL;
1062
1063 inbuf = PyUnicode_DATA(value);
1064 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001065 if (size == 0)
1066 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001067 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1068 PyErr_SetString(PyExc_OverflowError, "string is too long");
1069 return NULL;
1070 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001071 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001072 if (kind == sizeof(Tcl_UniChar))
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001073 return Tcl_NewUnicodeObj(inbuf, (int)size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001074 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001075 outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001076 /* Else overflow occurred, and we take the next exit */
1077 if (!outbuf) {
1078 PyErr_NoMemory();
1079 return NULL;
1080 }
1081 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001082 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1083 /* We cannot test for sizeof(Tcl_UniChar) directly,
1084 so we test for UTF-8 size instead. */
1085#if TCL_UTF_MAX == 3
1086 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001087 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001088 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001089 "character U+%x is above the range "
1090 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001091 ch);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001092 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001093 return NULL;
1094 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001095#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001096 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001097 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001098 result = Tcl_NewUnicodeObj(outbuf, (int)size);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001099 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001100 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001101 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001102
1103 if (PyTclObject_Check(value)) {
Miss Islington (bot)f7cefb42018-10-23 14:46:32 -07001104 return ((PyTclObject*)value)->value;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001106
1107 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001108 PyObject *v = PyObject_Str(value);
1109 if (!v)
1110 return 0;
1111 result = AsObj(v);
1112 Py_DECREF(v);
1113 return result;
1114 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001115}
1116
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001117static PyObject *
1118fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1119{
1120 int boolValue;
1121 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1122 return Tkinter_Error(tkapp);
1123 return PyBool_FromLong(boolValue);
1124}
1125
Martin v. Löwisffad6332002-11-26 09:28:05 +00001126static PyObject*
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001127fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1128{
1129 Tcl_WideInt wideValue;
1130 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001131 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1132 return PyLong_FromLongLong(wideValue);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001133 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1134 sizeof(wideValue),
1135 PY_LITTLE_ENDIAN,
1136 /* signed */ 1);
1137 }
1138 return NULL;
1139}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001140
1141#ifdef HAVE_LIBTOMMAMTH
1142static PyObject*
1143fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1144{
1145 mp_int bigValue;
1146 unsigned long numBytes;
1147 unsigned char *bytes;
1148 PyObject *res;
1149
1150 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1151 return Tkinter_Error(tkapp);
1152 numBytes = mp_unsigned_bin_size(&bigValue);
1153 bytes = PyMem_Malloc(numBytes);
1154 if (bytes == NULL) {
1155 mp_clear(&bigValue);
1156 return PyErr_NoMemory();
1157 }
1158 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1159 &numBytes) != MP_OKAY) {
1160 mp_clear(&bigValue);
1161 PyMem_Free(bytes);
1162 return PyErr_NoMemory();
1163 }
1164 res = _PyLong_FromByteArray(bytes, numBytes,
1165 /* big-endian */ 0,
1166 /* unsigned */ 0);
1167 PyMem_Free(bytes);
1168 if (res != NULL && bigValue.sign == MP_NEG) {
1169 PyObject *res2 = PyNumber_Negative(res);
1170 Py_DECREF(res);
1171 res = res2;
1172 }
1173 mp_clear(&bigValue);
1174 return res;
1175}
1176#endif
1177
Martin v. Löwisffad6332002-11-26 09:28:05 +00001178static PyObject*
1179FromObj(PyObject* tkapp, Tcl_Obj *value)
1180{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001181 PyObject *result = NULL;
1182 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001183 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001184
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001185 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001186 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001187 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001188
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001189 if (value->typePtr == app->BooleanType ||
1190 value->typePtr == app->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001191 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001192 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001193
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001194 if (value->typePtr == app->ByteArrayType) {
1195 int size;
1196 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1197 return PyBytes_FromStringAndSize(data, size);
1198 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001199
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001200 if (value->typePtr == app->DoubleType) {
1201 return PyFloat_FromDouble(value->internalRep.doubleValue);
1202 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001203
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001204 if (value->typePtr == app->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001205 long longValue;
1206 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1207 return PyLong_FromLong(longValue);
1208 /* If there is an error in the long conversion,
1209 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001210 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001211
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001212 if (value->typePtr == app->IntType ||
1213 value->typePtr == app->WideIntType) {
1214 result = fromWideIntObj(tkapp, value);
1215 if (result != NULL || PyErr_Occurred())
1216 return result;
1217 Tcl_ResetResult(interp);
1218 /* If there is an error in the wideInt conversion,
1219 fall through to bignum handling. */
1220 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001221
1222#ifdef HAVE_LIBTOMMAMTH
1223 if (value->typePtr == app->IntType ||
1224 value->typePtr == app->WideIntType ||
1225 value->typePtr == app->BignumType) {
1226 return fromBignumObj(tkapp, value);
1227 }
1228#endif
1229
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001230 if (value->typePtr == app->ListType) {
1231 int size;
1232 int i, status;
1233 PyObject *elem;
1234 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001235
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001236 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001237 if (status == TCL_ERROR)
1238 return Tkinter_Error(tkapp);
1239 result = PyTuple_New(size);
1240 if (!result)
1241 return NULL;
1242 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001243 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001244 if (status == TCL_ERROR) {
1245 Py_DECREF(result);
1246 return Tkinter_Error(tkapp);
1247 }
1248 elem = FromObj(tkapp, tcl_elem);
1249 if (!elem) {
1250 Py_DECREF(result);
1251 return NULL;
1252 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001253 PyTuple_SET_ITEM(result, i, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001254 }
1255 return result;
1256 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001257
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001258 if (value->typePtr == app->ProcBodyType) {
1259 /* fall through: return tcl object. */
1260 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001262 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001263 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001264 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001265 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001266 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001267
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001268#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001269 if (app->BooleanType == NULL &&
1270 strcmp(value->typePtr->name, "booleanString") == 0) {
1271 /* booleanString type is not registered in Tcl */
1272 app->BooleanType = value->typePtr;
1273 return fromBoolean(tkapp, value);
1274 }
1275#endif
1276
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001277#ifdef HAVE_LIBTOMMAMTH
1278 if (app->BignumType == NULL &&
1279 strcmp(value->typePtr->name, "bignum") == 0) {
1280 /* bignum type is not registered in Tcl */
1281 app->BignumType = value->typePtr;
1282 return fromBignumObj(tkapp, value);
1283 }
1284#endif
1285
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001286 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001287}
1288
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001289/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001290TCL_DECLARE_MUTEX(call_mutex)
1291
1292typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001293 Tcl_Event ev; /* Must be first */
1294 TkappObject *self;
1295 PyObject *args;
1296 int flags;
1297 PyObject **res;
1298 PyObject **exc_type, **exc_value, **exc_tb;
1299 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001300} Tkapp_CallEvent;
1301
1302void
1303Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001304{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001305 int i;
1306 for (i = 0; i < objc; i++)
1307 Tcl_DecrRefCount(objv[i]);
1308 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001309 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001310}
Guido van Rossum18468821994-06-20 07:49:28 +00001311
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001312/* Convert Python objects to Tcl objects. This must happen in the
1313 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001314
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001315static Tcl_Obj**
1316Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1317{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001318 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001319 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001320 if (args == NULL)
1321 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001322
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001323 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001324 objv[0] = AsObj(args);
Serhiy Storchaka0b3ec192017-03-23 17:53:47 +02001325 if (objv[0] == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 goto finally;
1327 objc = 1;
1328 Tcl_IncrRefCount(objv[0]);
1329 }
1330 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001331 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001332
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001333 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001334 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001335 PyErr_SetString(PyExc_OverflowError,
1336 PyTuple_Check(args) ? "tuple is too long" :
1337 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001338 return NULL;
1339 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001340 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001341 if (objv == NULL) {
1342 PyErr_NoMemory();
1343 objc = 0;
1344 goto finally;
1345 }
1346 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001348 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001349 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 if (v == Py_None) {
1351 objc = i;
1352 break;
1353 }
1354 objv[i] = AsObj(v);
1355 if (!objv[i]) {
1356 /* Reset objc, so it attempts to clear
1357 objects only up to i. */
1358 objc = i;
1359 goto finally;
1360 }
1361 Tcl_IncrRefCount(objv[i]);
1362 }
1363 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001364 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001365 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001366finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001367 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001368 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001369}
Guido van Rossum212643f1998-04-29 16:22:14 +00001370
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001371/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001372
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001373static PyObject*
1374Tkapp_CallResult(TkappObject *self)
1375{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001376 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001377 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001378 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001379 /* Not sure whether the IncrRef is necessary, but something
1380 may overwrite the interpreter result while we are
1381 converting it. */
1382 Tcl_IncrRefCount(value);
1383 res = FromObj((PyObject*)self, value);
1384 Tcl_DecrRefCount(value);
1385 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001386 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001387 }
1388 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001389}
Guido van Rossum632de272000-03-29 00:19:50 +00001390
Benjamin Peterson5879d412009-03-30 14:51:56 +00001391
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001392/* Tkapp_CallProc is the event procedure that is executed in the context of
1393 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1394 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001395
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001396static int
1397Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1398{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001399 Tcl_Obj *objStore[ARGSZ];
1400 Tcl_Obj **objv;
1401 int objc;
1402 int i;
1403 ENTER_PYTHON
1404 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1405 if (!objv) {
1406 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1407 *(e->res) = NULL;
1408 }
1409 LEAVE_PYTHON
1410 if (!objv)
1411 goto done;
1412 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1413 ENTER_PYTHON
1414 if (i == TCL_ERROR) {
1415 *(e->res) = NULL;
1416 *(e->exc_type) = NULL;
1417 *(e->exc_tb) = NULL;
1418 *(e->exc_value) = PyObject_CallFunction(
1419 Tkinter_TclError, "s",
1420 Tcl_GetStringResult(e->self->interp));
1421 }
1422 else {
1423 *(e->res) = Tkapp_CallResult(e->self);
1424 }
1425 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001426
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001427 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001428done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001429 /* Wake up calling thread. */
1430 Tcl_MutexLock(&call_mutex);
1431 Tcl_ConditionNotify(e->done);
1432 Tcl_MutexUnlock(&call_mutex);
1433 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001434}
1435
Benjamin Peterson5879d412009-03-30 14:51:56 +00001436
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001437/* This is the main entry point for calling a Tcl command.
1438 It supports three cases, with regard to threading:
1439 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1440 the context of the calling thread.
1441 2. Tcl is threaded, caller of the command is in the interpreter thread:
1442 Execute the command in the calling thread. Since the Tcl lock will
1443 not be used, we can merge that with case 1.
1444 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1445 the interpreter thread. Allocation of Tcl objects needs to occur in the
1446 interpreter thread, so we ship the PyObject* args to the target thread,
1447 and perform processing there. */
1448
1449static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001450Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001451{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001452 Tcl_Obj *objStore[ARGSZ];
1453 Tcl_Obj **objv = NULL;
1454 int objc, i;
1455 PyObject *res = NULL;
1456 TkappObject *self = (TkappObject*)selfptr;
1457 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001459 /* If args is a single tuple, replace with contents of tuple */
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001460 if (PyTuple_GET_SIZE(args) == 1) {
1461 PyObject *item = PyTuple_GET_ITEM(args, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001462 if (PyTuple_Check(item))
1463 args = item;
1464 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001465 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1466 /* We cannot call the command directly. Instead, we must
1467 marshal the parameters to the interpreter thread. */
1468 Tkapp_CallEvent *ev;
1469 Tcl_Condition cond = NULL;
1470 PyObject *exc_type, *exc_value, *exc_tb;
1471 if (!WaitForMainloop(self))
1472 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001473 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1474 if (ev == NULL) {
1475 PyErr_NoMemory();
1476 return NULL;
1477 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001478 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1479 ev->self = self;
1480 ev->args = args;
1481 ev->res = &res;
1482 ev->exc_type = &exc_type;
1483 ev->exc_value = &exc_value;
1484 ev->exc_tb = &exc_tb;
1485 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001487 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001488
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001489 if (res == NULL) {
1490 if (exc_type)
1491 PyErr_Restore(exc_type, exc_value, exc_tb);
1492 else
1493 PyErr_SetObject(Tkinter_TclError, exc_value);
1494 }
1495 Tcl_ConditionFinalize(&cond);
1496 }
1497 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001498 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001499
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001500 objv = Tkapp_CallArgs(args, objStore, &objc);
1501 if (!objv)
1502 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001503
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001504 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001506 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001508 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510 if (i == TCL_ERROR)
1511 Tkinter_Error(selfptr);
1512 else
1513 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001514
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001515 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001517 Tkapp_CallDeallocArgs(objv, objStore, objc);
1518 }
1519 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001520}
1521
1522
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001523/*[clinic input]
1524_tkinter.tkapp.eval
1525
1526 script: str
1527 /
1528
1529[clinic start generated code]*/
1530
Barry Warsawfa701a81997-01-16 00:15:11 +00001531static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001532_tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1533/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001534{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001535 PyObject *res = NULL;
1536 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001537
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001538 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001539 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541 ENTER_TCL
1542 err = Tcl_Eval(Tkapp_Interp(self), script);
1543 ENTER_OVERLAP
1544 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001545 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001546 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001547 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001548 LEAVE_OVERLAP_TCL
1549 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001550}
1551
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001552/*[clinic input]
1553_tkinter.tkapp.evalfile
1554
1555 fileName: str
1556 /
1557
1558[clinic start generated code]*/
1559
Guido van Rossum18468821994-06-20 07:49:28 +00001560static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001561_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1562/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001563{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001564 PyObject *res = NULL;
1565 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001566
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001567 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001569
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001570 ENTER_TCL
1571 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1572 ENTER_OVERLAP
1573 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001574 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001575 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001576 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001577 LEAVE_OVERLAP_TCL
1578 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001579}
1580
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001581/*[clinic input]
1582_tkinter.tkapp.record
1583
1584 script: str
1585 /
1586
1587[clinic start generated code]*/
1588
Guido van Rossum18468821994-06-20 07:49:28 +00001589static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001590_tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1591/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001592{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001593 PyObject *res = NULL;
1594 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001595
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001596 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001597 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001598
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001599 ENTER_TCL
1600 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1601 ENTER_OVERLAP
1602 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001603 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001604 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001605 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001606 LEAVE_OVERLAP_TCL
1607 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001608}
1609
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001610/*[clinic input]
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001611_tkinter.tkapp.adderrorinfo
Guido van Rossum18468821994-06-20 07:49:28 +00001612
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001613 msg: str
1614 /
1615
1616[clinic start generated code]*/
1617
1618static PyObject *
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001619_tkinter_tkapp_adderrorinfo_impl(TkappObject *self, const char *msg)
1620/*[clinic end generated code: output=52162eaca2ee53cb input=f4b37aec7c7e8c77]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001621{
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001622 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001623 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001625 ENTER_TCL
1626 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1627 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001628
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001629 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001630}
1631
Barry Warsawfa701a81997-01-16 00:15:11 +00001632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001633
Guido van Rossum18468821994-06-20 07:49:28 +00001634/** Tcl Variable **/
1635
Benjamin Peterson5879d412009-03-30 14:51:56 +00001636typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1637
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001638TCL_DECLARE_MUTEX(var_mutex)
1639
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001640typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001641 Tcl_Event ev; /* must be first */
1642 PyObject *self;
1643 PyObject *args;
1644 int flags;
1645 EventFunc func;
1646 PyObject **res;
1647 PyObject **exc_type;
1648 PyObject **exc_val;
1649 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001650} VarEvent;
1651
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001652/*[python]
1653
1654class varname_converter(CConverter):
1655 type = 'const char *'
1656 converter = 'varname_converter'
1657
1658[python]*/
1659/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1660
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001661static int
1662varname_converter(PyObject *in, void *_out)
1663{
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +02001664 const char *s;
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001665 const char **out = (const char**)_out;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001666 if (PyBytes_Check(in)) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001667 if (PyBytes_GET_SIZE(in) > INT_MAX) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001668 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1669 return 0;
1670 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001671 s = PyBytes_AS_STRING(in);
1672 if (strlen(s) != (size_t)PyBytes_GET_SIZE(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001673 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001674 return 0;
1675 }
1676 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001677 return 1;
1678 }
1679 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001680 Py_ssize_t size;
1681 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001682 if (s == NULL) {
1683 return 0;
1684 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001685 if (size > INT_MAX) {
1686 PyErr_SetString(PyExc_OverflowError, "string is too long");
1687 return 0;
1688 }
Victor Stinner706768c2014-08-16 01:03:39 +02001689 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001690 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001691 return 0;
1692 }
1693 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001694 return 1;
1695 }
1696 if (PyTclObject_Check(in)) {
1697 *out = PyTclObject_TclString(in);
1698 return 1;
1699 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001700 PyErr_Format(PyExc_TypeError,
1701 "must be str, bytes or Tcl_Obj, not %.50s",
1702 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001703 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001704}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001705
Benjamin Peterson5879d412009-03-30 14:51:56 +00001706
Martin v. Löwis59683e82008-06-13 07:50:45 +00001707static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001708var_perform(VarEvent *ev)
1709{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001710 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1711 if (!*(ev->res)) {
1712 PyObject *exc, *val, *tb;
1713 PyErr_Fetch(&exc, &val, &tb);
1714 PyErr_NormalizeException(&exc, &val, &tb);
1715 *(ev->exc_type) = exc;
1716 *(ev->exc_val) = val;
Serhiy Storchaka3ec5f422016-10-28 12:14:34 +03001717 Py_XDECREF(tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001718 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001719
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001720}
1721
1722static int
1723var_proc(VarEvent* ev, int flags)
1724{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001725 ENTER_PYTHON
1726 var_perform(ev);
1727 Tcl_MutexLock(&var_mutex);
1728 Tcl_ConditionNotify(ev->cond);
1729 Tcl_MutexUnlock(&var_mutex);
1730 LEAVE_PYTHON
1731 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001732}
1733
Benjamin Peterson5879d412009-03-30 14:51:56 +00001734
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001735static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001736var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001737{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 TkappObject *self = (TkappObject*)selfptr;
1739 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001740 VarEvent *ev;
1741 PyObject *res, *exc_type, *exc_val;
1742 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001743
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001744 /* The current thread is not the interpreter thread. Marshal
1745 the call to the interpreter thread, then wait for
1746 completion. */
1747 if (!WaitForMainloop(self))
1748 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001749
Serhiy Storchaka07940882014-09-11 10:38:54 +03001750 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1751 if (ev == NULL) {
1752 PyErr_NoMemory();
1753 return NULL;
1754 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001755 ev->self = selfptr;
1756 ev->args = args;
1757 ev->flags = flags;
1758 ev->func = func;
1759 ev->res = &res;
1760 ev->exc_type = &exc_type;
1761 ev->exc_val = &exc_val;
1762 ev->cond = &cond;
1763 ev->ev.proc = (Tcl_EventProc*)var_proc;
1764 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1765 Tcl_ConditionFinalize(&cond);
1766 if (!res) {
1767 PyErr_SetObject(exc_type, exc_val);
1768 Py_DECREF(exc_type);
1769 Py_DECREF(exc_val);
1770 return NULL;
1771 }
1772 return res;
1773 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001774 /* Tcl is not threaded, or this is the interpreter thread. */
1775 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001776}
1777
Guido van Rossum18468821994-06-20 07:49:28 +00001778static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001779SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001780{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001781 const char *name1, *name2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001782 PyObject *newValue;
1783 PyObject *res = NULL;
1784 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001785
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001786 switch (PyTuple_GET_SIZE(args)) {
1787 case 2:
1788 if (!PyArg_ParseTuple(args, "O&O:setvar",
1789 varname_converter, &name1, &newValue))
1790 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001791 /* XXX Acquire tcl lock??? */
1792 newval = AsObj(newValue);
1793 if (newval == NULL)
1794 return NULL;
1795 ENTER_TCL
1796 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1797 newval, flags);
1798 ENTER_OVERLAP
1799 if (!ok)
1800 Tkinter_Error(self);
1801 else {
1802 res = Py_None;
1803 Py_INCREF(res);
1804 }
1805 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001806 break;
1807 case 3:
1808 if (!PyArg_ParseTuple(args, "ssO:setvar",
1809 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001810 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001811 CHECK_STRING_LENGTH(name1);
1812 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001813 /* XXX must hold tcl lock already??? */
1814 newval = AsObj(newValue);
1815 ENTER_TCL
1816 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1817 ENTER_OVERLAP
1818 if (!ok)
1819 Tkinter_Error(self);
1820 else {
1821 res = Py_None;
1822 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001823 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001824 LEAVE_OVERLAP_TCL
1825 break;
1826 default:
1827 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1828 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001829 }
1830 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001831}
1832
1833static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001834Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001835{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001836 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001837}
1838
1839static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001840Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001841{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001842 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001843}
1844
Barry Warsawfa701a81997-01-16 00:15:11 +00001845
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001846
Guido van Rossum18468821994-06-20 07:49:28 +00001847static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001848GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001849{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001850 const char *name1, *name2=NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001851 PyObject *res = NULL;
1852 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001853
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001854 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1855 varname_converter, &name1, &name2))
1856 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001857
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001858 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001859 ENTER_TCL
1860 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1861 ENTER_OVERLAP
1862 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001863 PyErr_SetString(Tkinter_TclError,
1864 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001865 } else {
1866 if (((TkappObject*)self)->wantobjects) {
1867 res = FromObj(self, tres);
1868 }
1869 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001870 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001871 }
1872 }
1873 LEAVE_OVERLAP_TCL
1874 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001875}
1876
1877static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001878Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001879{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001880 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001881}
1882
1883static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001884Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001885{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001886 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001887}
1888
Barry Warsawfa701a81997-01-16 00:15:11 +00001889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001890
Guido van Rossum18468821994-06-20 07:49:28 +00001891static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001892UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001893{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001894 char *name1, *name2=NULL;
1895 int code;
1896 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001897
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001898 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1899 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001900
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001901 CHECK_STRING_LENGTH(name1);
1902 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001903 ENTER_TCL
1904 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1905 ENTER_OVERLAP
1906 if (code == TCL_ERROR)
1907 res = Tkinter_Error(self);
1908 else {
1909 Py_INCREF(Py_None);
1910 res = Py_None;
1911 }
1912 LEAVE_OVERLAP_TCL
1913 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001914}
1915
1916static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001917Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001918{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001919 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001920}
1921
1922static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001923Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001924{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001925 return var_invoke(UnsetVar, self, args,
1926 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001927}
1928
Barry Warsawfa701a81997-01-16 00:15:11 +00001929
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001930
Guido van Rossum18468821994-06-20 07:49:28 +00001931/** Tcl to Python **/
1932
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001933/*[clinic input]
1934_tkinter.tkapp.getint
1935
1936 arg: object
1937 /
1938
1939[clinic start generated code]*/
1940
Guido van Rossum18468821994-06-20 07:49:28 +00001941static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001942_tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
1943/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001944{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001945 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001946 Tcl_Obj *value;
1947 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00001948
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001949 if (PyLong_Check(arg)) {
1950 Py_INCREF(arg);
1951 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001952 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001953
Serhiy Storchaka645058d2015-05-06 14:00:04 +03001954 if (PyTclObject_Check(arg)) {
1955 value = ((PyTclObject*)arg)->value;
1956 Tcl_IncrRefCount(value);
1957 }
1958 else {
1959 if (!PyArg_Parse(arg, "s:getint", &s))
1960 return NULL;
1961 CHECK_STRING_LENGTH(s);
1962 value = Tcl_NewStringObj(s, -1);
1963 if (value == NULL)
1964 return Tkinter_Error((PyObject *)self);
1965 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001966 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
1967 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
1968
1969 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
1970 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
1971 */
1972#ifdef HAVE_LIBTOMMAMTH
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001973 result = fromBignumObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001974#else
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001975 result = fromWideIntObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001976#endif
1977 Tcl_DecrRefCount(value);
1978 if (result != NULL || PyErr_Occurred())
1979 return result;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001980 return Tkinter_Error((PyObject *)self);
Guido van Rossum18468821994-06-20 07:49:28 +00001981}
1982
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001983/*[clinic input]
1984_tkinter.tkapp.getdouble
1985
1986 arg: object
1987 /
1988
1989[clinic start generated code]*/
1990
Guido van Rossum18468821994-06-20 07:49:28 +00001991static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001992_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
1993/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001994{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001995 char *s;
1996 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001997
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001998 if (PyFloat_Check(arg)) {
1999 Py_INCREF(arg);
2000 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002001 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002002
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002003 if (PyNumber_Check(arg)) {
2004 return PyNumber_Float(arg);
2005 }
2006
2007 if (PyTclObject_Check(arg)) {
2008 if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
2009 ((PyTclObject*)arg)->value,
2010 &v) == TCL_ERROR)
2011 return Tkinter_Error((PyObject *)self);
2012 return PyFloat_FromDouble(v);
2013 }
2014
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002015 if (!PyArg_Parse(arg, "s:getdouble", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002016 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002017 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002018 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002019 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002020 return PyFloat_FromDouble(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002021}
2022
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002023/*[clinic input]
2024_tkinter.tkapp.getboolean
2025
2026 arg: object
2027 /
2028
2029[clinic start generated code]*/
2030
Guido van Rossum18468821994-06-20 07:49:28 +00002031static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002032_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
2033/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002034{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002035 char *s;
2036 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002037
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002038 if (PyLong_Check(arg)) { /* int or bool */
2039 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002040 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002041
2042 if (PyTclObject_Check(arg)) {
2043 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2044 ((PyTclObject*)arg)->value,
2045 &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002046 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002047 return PyBool_FromLong(v);
2048 }
2049
2050 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002051 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002052 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002053 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002054 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002055 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002056}
2057
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002058/*[clinic input]
2059_tkinter.tkapp.exprstring
2060
2061 s: str
2062 /
2063
2064[clinic start generated code]*/
2065
Guido van Rossum18468821994-06-20 07:49:28 +00002066static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002067_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2068/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002069{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002070 PyObject *res = NULL;
2071 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002072
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002073 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002074 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002075
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002076 ENTER_TCL
2077 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2078 ENTER_OVERLAP
2079 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002080 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002081 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002082 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002083 LEAVE_OVERLAP_TCL
2084 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002085}
2086
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002087/*[clinic input]
2088_tkinter.tkapp.exprlong
2089
2090 s: str
2091 /
2092
2093[clinic start generated code]*/
2094
Guido van Rossum18468821994-06-20 07:49:28 +00002095static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002096_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2097/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002098{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002099 PyObject *res = NULL;
2100 int retval;
2101 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002102
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002103 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002104 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002105
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002106 ENTER_TCL
2107 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2108 ENTER_OVERLAP
2109 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002110 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002111 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002112 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002113 LEAVE_OVERLAP_TCL
2114 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002115}
2116
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002117/*[clinic input]
2118_tkinter.tkapp.exprdouble
2119
2120 s: str
2121 /
2122
2123[clinic start generated code]*/
2124
Guido van Rossum18468821994-06-20 07:49:28 +00002125static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002126_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2127/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002128{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002129 PyObject *res = NULL;
2130 double v;
2131 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002132
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002133 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002134 CHECK_TCL_APPARTMENT;
2135 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2136 ENTER_TCL
2137 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2138 ENTER_OVERLAP
2139 PyFPE_END_PROTECT(retval)
2140 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002141 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002143 res = PyFloat_FromDouble(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002144 LEAVE_OVERLAP_TCL
2145 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002146}
2147
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002148/*[clinic input]
2149_tkinter.tkapp.exprboolean
2150
2151 s: str
2152 /
2153
2154[clinic start generated code]*/
2155
Guido van Rossum18468821994-06-20 07:49:28 +00002156static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002157_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2158/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002159{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 PyObject *res = NULL;
2161 int retval;
2162 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002163
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002164 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002165 CHECK_TCL_APPARTMENT;
2166 ENTER_TCL
2167 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2168 ENTER_OVERLAP
2169 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002170 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002171 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002172 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002173 LEAVE_OVERLAP_TCL
2174 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002175}
2176
Barry Warsawfa701a81997-01-16 00:15:11 +00002177
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002178
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002179/*[clinic input]
2180_tkinter.tkapp.splitlist
2181
2182 arg: object
2183 /
2184
2185[clinic start generated code]*/
2186
Guido van Rossum18468821994-06-20 07:49:28 +00002187static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002188_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2189/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002190{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002191 char *list;
2192 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002193 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002194 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002195 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002196
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002197 if (PyTclObject_Check(arg)) {
2198 int objc;
2199 Tcl_Obj **objv;
2200 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2201 ((PyTclObject*)arg)->value,
2202 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002203 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002204 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002205 if (!(v = PyTuple_New(objc)))
2206 return NULL;
2207 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002208 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002209 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002210 Py_DECREF(v);
2211 return NULL;
2212 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002213 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002214 }
2215 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002216 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002217 if (PyTuple_Check(arg)) {
2218 Py_INCREF(arg);
2219 return arg;
2220 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002221 if (PyList_Check(arg)) {
2222 return PySequence_Tuple(arg);
2223 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002224
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002225 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002226 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002227
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002228 if (strlen(list) >= INT_MAX) {
2229 PyErr_SetString(PyExc_OverflowError, "string is too long");
2230 PyMem_Free(list);
2231 return NULL;
2232 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002233 if (Tcl_SplitList(Tkapp_Interp(self), list,
2234 &argc, &argv) == TCL_ERROR) {
2235 PyMem_Free(list);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002236 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002237 }
Guido van Rossum18468821994-06-20 07:49:28 +00002238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002239 if (!(v = PyTuple_New(argc)))
2240 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002241
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002242 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002243 PyObject *s = unicodeFromTclString(argv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002244 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002245 Py_DECREF(v);
2246 v = NULL;
2247 goto finally;
2248 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002249 PyTuple_SET_ITEM(v, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002250 }
Guido van Rossum18468821994-06-20 07:49:28 +00002251
Barry Warsawfa701a81997-01-16 00:15:11 +00002252 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002253 ckfree(FREECAST argv);
2254 PyMem_Free(list);
2255 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002256}
2257
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002258/*[clinic input]
2259_tkinter.tkapp.split
2260
2261 arg: object
2262 /
2263
2264[clinic start generated code]*/
2265
Guido van Rossum18468821994-06-20 07:49:28 +00002266static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002267_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2268/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002269{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002270 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002271 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002272
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002273 if (PyTclObject_Check(arg)) {
2274 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2275 int objc;
2276 Tcl_Obj **objv;
2277 int i;
2278 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2279 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002280 return FromObj((PyObject*)self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002281 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002282 if (objc == 0)
2283 return PyUnicode_FromString("");
2284 if (objc == 1)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002285 return FromObj((PyObject*)self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002286 if (!(v = PyTuple_New(objc)))
2287 return NULL;
2288 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002289 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002290 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002291 Py_DECREF(v);
2292 return NULL;
2293 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002294 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002295 }
2296 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002297 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002298 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002299 return SplitObj(arg);
2300
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002301 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002302 return NULL;
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002303 if (strlen(list) >= INT_MAX) {
2304 PyErr_SetString(PyExc_OverflowError, "string is too long");
2305 PyMem_Free(list);
2306 return NULL;
2307 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002308 v = Split(list);
2309 PyMem_Free(list);
2310 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002311}
2312
Barry Warsawfa701a81997-01-16 00:15:11 +00002313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002314
Guido van Rossum18468821994-06-20 07:49:28 +00002315/** Tcl Command **/
2316
Guido van Rossum00d93061998-05-28 23:06:38 +00002317/* Client data struct */
2318typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002319 PyObject *self;
2320 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002321} PythonCmd_ClientData;
2322
2323static int
Fred Drake509d79a2000-07-08 04:04:38 +00002324PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002325{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002326 errorInCmd = 1;
2327 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2328 LEAVE_PYTHON
2329 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002330}
2331
Guido van Rossum18468821994-06-20 07:49:28 +00002332/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002333 * function or method.
2334 */
Guido van Rossum18468821994-06-20 07:49:28 +00002335static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002336PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002337{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002338 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002339 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002340 int i, rv;
2341 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002343 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002345 /* TBD: no error checking here since we know, via the
2346 * Tkapp_CreateCommand() that the client data is a two-tuple
2347 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002348 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002350 /* Create argument list (argv1, ..., argvN) */
2351 if (!(arg = PyTuple_New(argc - 1)))
2352 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002353
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002354 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002355 PyObject *s = unicodeFromTclString(argv[i + 1]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002356 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002357 Py_DECREF(arg);
2358 return PythonCmd_Error(interp);
2359 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002360 PyTuple_SET_ITEM(arg, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002361 }
INADA Naoki72dccde2017-02-16 09:26:01 +09002362 res = PyObject_Call(func, arg, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002363 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002364
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002365 if (res == NULL)
2366 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002367
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002368 obj_res = AsObj(res);
2369 if (obj_res == NULL) {
2370 Py_DECREF(res);
2371 return PythonCmd_Error(interp);
2372 }
2373 else {
2374 Tcl_SetObjResult(interp, obj_res);
2375 rv = TCL_OK;
2376 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002377
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002378 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002380 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002382 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002383}
2384
2385static void
Fred Drake509d79a2000-07-08 04:04:38 +00002386PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002387{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002388 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002390 ENTER_PYTHON
2391 Py_XDECREF(data->self);
2392 Py_XDECREF(data->func);
2393 PyMem_DEL(data);
2394 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002395}
2396
Barry Warsawfa701a81997-01-16 00:15:11 +00002397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002398
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002399
2400TCL_DECLARE_MUTEX(command_mutex)
2401
2402typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002403 Tcl_Event ev;
2404 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002405 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002406 int create;
2407 int *status;
2408 ClientData *data;
2409 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002410} CommandEvent;
2411
2412static int
2413Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002414{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002415 if (ev->create)
2416 *ev->status = Tcl_CreateCommand(
2417 ev->interp, ev->name, PythonCmd,
2418 ev->data, PythonCmdDelete) == NULL;
2419 else
2420 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2421 Tcl_MutexLock(&command_mutex);
2422 Tcl_ConditionNotify(ev->done);
2423 Tcl_MutexUnlock(&command_mutex);
2424 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002425}
2426
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002427/*[clinic input]
2428_tkinter.tkapp.createcommand
2429
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002430 name: str
2431 func: object
2432 /
2433
2434[clinic start generated code]*/
2435
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002436static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002437_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2438 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002439/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002440{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002441 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002442 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002443
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002444 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002445 if (!PyCallable_Check(func)) {
2446 PyErr_SetString(PyExc_TypeError, "command not callable");
2447 return NULL;
2448 }
Guido van Rossum18468821994-06-20 07:49:28 +00002449
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002450 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2451 !WaitForMainloop(self))
2452 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002454 data = PyMem_NEW(PythonCmd_ClientData, 1);
2455 if (!data)
2456 return PyErr_NoMemory();
2457 Py_INCREF(self);
2458 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002459 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002460 data->func = func;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002461 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2462 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002463 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2464 if (ev == NULL) {
2465 PyErr_NoMemory();
2466 PyMem_DEL(data);
2467 return NULL;
2468 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002469 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2470 ev->interp = self->interp;
2471 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002472 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002473 ev->data = (ClientData)data;
2474 ev->status = &err;
2475 ev->done = &cond;
2476 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2477 Tcl_ConditionFinalize(&cond);
2478 }
2479 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002480 {
2481 ENTER_TCL
2482 err = Tcl_CreateCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002483 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002484 (ClientData)data, PythonCmdDelete) == NULL;
2485 LEAVE_TCL
2486 }
2487 if (err) {
2488 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2489 PyMem_DEL(data);
2490 return NULL;
2491 }
Guido van Rossum18468821994-06-20 07:49:28 +00002492
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002493 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002494}
2495
Barry Warsawfa701a81997-01-16 00:15:11 +00002496
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002497
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002498/*[clinic input]
2499_tkinter.tkapp.deletecommand
2500
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002501 name: str
2502 /
2503
2504[clinic start generated code]*/
2505
Guido van Rossum18468821994-06-20 07:49:28 +00002506static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002507_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002508/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002509{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002510 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002511
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002512 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002513
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002514 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2515 Tcl_Condition cond = NULL;
2516 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002517 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2518 if (ev == NULL) {
2519 PyErr_NoMemory();
2520 return NULL;
2521 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002522 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2523 ev->interp = self->interp;
2524 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002525 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002526 ev->status = &err;
2527 ev->done = &cond;
2528 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2529 &command_mutex);
2530 Tcl_ConditionFinalize(&cond);
2531 }
2532 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002533 {
2534 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002535 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002536 LEAVE_TCL
2537 }
2538 if (err == -1) {
2539 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2540 return NULL;
2541 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002542 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002543}
2544
Barry Warsawfa701a81997-01-16 00:15:11 +00002545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002546
Guido van Rossum00d93061998-05-28 23:06:38 +00002547#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002548/** File Handler **/
2549
Guido van Rossum00d93061998-05-28 23:06:38 +00002550typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002551 PyObject *func;
2552 PyObject *file;
2553 int id;
2554 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002555} FileHandler_ClientData;
2556
2557static FileHandler_ClientData *HeadFHCD;
2558
2559static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002560NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002561{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002562 FileHandler_ClientData *p;
2563 p = PyMem_NEW(FileHandler_ClientData, 1);
2564 if (p != NULL) {
2565 Py_XINCREF(func);
2566 Py_XINCREF(file);
2567 p->func = func;
2568 p->file = file;
2569 p->id = id;
2570 p->next = HeadFHCD;
2571 HeadFHCD = p;
2572 }
2573 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002574}
2575
2576static void
Fred Drake509d79a2000-07-08 04:04:38 +00002577DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002578{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002580
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002581 pp = &HeadFHCD;
2582 while ((p = *pp) != NULL) {
2583 if (p->id == id) {
2584 *pp = p->next;
2585 Py_XDECREF(p->func);
2586 Py_XDECREF(p->file);
2587 PyMem_DEL(p);
2588 }
2589 else
2590 pp = &p->next;
2591 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002592}
2593
Guido van Rossuma597dde1995-01-10 20:56:29 +00002594static void
Fred Drake509d79a2000-07-08 04:04:38 +00002595FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002596{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002597 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
INADA Naoki72dccde2017-02-16 09:26:01 +09002598 PyObject *func, *file, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002600 ENTER_PYTHON
2601 func = data->func;
2602 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002603
INADA Naoki72dccde2017-02-16 09:26:01 +09002604 res = PyObject_CallFunction(func, "Oi", file, mask);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002605 if (res == NULL) {
2606 errorInCmd = 1;
2607 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2608 }
2609 Py_XDECREF(res);
2610 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002611}
2612
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002613/*[clinic input]
2614_tkinter.tkapp.createfilehandler
2615
2616 file: object
2617 mask: int
2618 func: object
2619 /
2620
2621[clinic start generated code]*/
2622
Guido van Rossum18468821994-06-20 07:49:28 +00002623static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002624_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2625 int mask, PyObject *func)
2626/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002627{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002628 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002629 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002631 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002633 tfile = PyObject_AsFileDescriptor(file);
2634 if (tfile < 0)
2635 return NULL;
2636 if (!PyCallable_Check(func)) {
2637 PyErr_SetString(PyExc_TypeError, "bad argument list");
2638 return NULL;
2639 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002640
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002641 data = NewFHCD(func, file, tfile);
2642 if (data == NULL)
2643 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002645 /* Ought to check for null Tcl_File object... */
2646 ENTER_TCL
2647 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2648 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002649 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002650}
2651
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002652/*[clinic input]
2653_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002654
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002655 file: object
2656 /
2657
2658[clinic start generated code]*/
2659
2660static PyObject *
2661_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2662/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2663{
2664 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002666 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002668 tfile = PyObject_AsFileDescriptor(file);
2669 if (tfile < 0)
2670 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002672 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002674 /* Ought to check for null Tcl_File object... */
2675 ENTER_TCL
2676 Tcl_DeleteFileHandler(tfile);
2677 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002678 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002679}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002680#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002682
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002683/**** Tktt Object (timer token) ****/
2684
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002685static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002686
Guido van Rossum00d93061998-05-28 23:06:38 +00002687typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002688 PyObject_HEAD
2689 Tcl_TimerToken token;
2690 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002691} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002692
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002693/*[clinic input]
2694_tkinter.tktimertoken.deletetimerhandler
2695
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002696[clinic start generated code]*/
2697
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002698static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002699_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002700/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002701{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002702 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002703 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002704
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002705 if (v->token != NULL) {
2706 Tcl_DeleteTimerHandler(v->token);
2707 v->token = NULL;
2708 }
2709 if (func != NULL) {
2710 v->func = NULL;
2711 Py_DECREF(func);
2712 Py_DECREF(v); /* See Tktt_New() */
2713 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002714 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002715}
2716
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002717static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002718Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002719{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002720 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002721
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002722 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002723 if (v == NULL)
2724 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002725 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002726
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002727 Py_INCREF(func);
2728 v->token = NULL;
2729 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002730
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002731 /* Extra reference, deleted when called or when handler is deleted */
2732 Py_INCREF(v);
2733 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002734}
2735
2736static void
Fred Drake509d79a2000-07-08 04:04:38 +00002737Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002738{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002739 TkttObject *v = (TkttObject *)self;
2740 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002741 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002743 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002744
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002745 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002746 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002747}
2748
Guido van Rossum597ac201998-05-12 14:36:19 +00002749static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002750Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002751{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002752 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002753 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2754 v,
2755 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002756}
2757
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002758/** Timer Handler **/
2759
2760static void
Fred Drake509d79a2000-07-08 04:04:38 +00002761TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002762{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002763 TkttObject *v = (TkttObject *)clientData;
2764 PyObject *func = v->func;
2765 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002766
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002767 if (func == NULL)
2768 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002769
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002770 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002771
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002772 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002773
INADA Naoki72dccde2017-02-16 09:26:01 +09002774 res = _PyObject_CallNoArg(func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002775 Py_DECREF(func);
2776 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002777
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002778 if (res == NULL) {
2779 errorInCmd = 1;
2780 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2781 }
2782 else
2783 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002784
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002785 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002786}
2787
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002788/*[clinic input]
2789_tkinter.tkapp.createtimerhandler
2790
2791 milliseconds: int
2792 func: object
2793 /
2794
2795[clinic start generated code]*/
2796
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002797static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002798_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2799 PyObject *func)
2800/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002801{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002802 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002803
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002804 if (!PyCallable_Check(func)) {
2805 PyErr_SetString(PyExc_TypeError, "bad argument list");
2806 return NULL;
2807 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002808
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002809 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002810
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002811 v = Tktt_New(func);
2812 if (v) {
2813 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2814 (ClientData)v);
2815 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002816
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002817 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002818}
2819
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002820
Guido van Rossum18468821994-06-20 07:49:28 +00002821/** Event Loop **/
2822
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002823/*[clinic input]
2824_tkinter.tkapp.mainloop
2825
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002826 threshold: int = 0
2827 /
2828
2829[clinic start generated code]*/
2830
Guido van Rossum18468821994-06-20 07:49:28 +00002831static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002832_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002833/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002834{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002835 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002837 CHECK_TCL_APPARTMENT;
2838 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002839
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002840 quitMainLoop = 0;
2841 while (Tk_GetNumMainWindows() > threshold &&
2842 !quitMainLoop &&
2843 !errorInCmd)
2844 {
2845 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002846
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002847 if (self->threaded) {
2848 /* Allow other Python threads to run. */
2849 ENTER_TCL
2850 result = Tcl_DoOneEvent(0);
2851 LEAVE_TCL
2852 }
2853 else {
2854 Py_BEGIN_ALLOW_THREADS
2855 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2856 tcl_tstate = tstate;
2857 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2858 tcl_tstate = NULL;
2859 if(tcl_lock)PyThread_release_lock(tcl_lock);
2860 if (result == 0)
2861 Sleep(Tkinter_busywaitinterval);
2862 Py_END_ALLOW_THREADS
2863 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002864
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002865 if (PyErr_CheckSignals() != 0) {
2866 self->dispatching = 0;
2867 return NULL;
2868 }
2869 if (result < 0)
2870 break;
2871 }
2872 self->dispatching = 0;
2873 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002874
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002875 if (errorInCmd) {
2876 errorInCmd = 0;
2877 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2878 excInCmd = valInCmd = trbInCmd = NULL;
2879 return NULL;
2880 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002881 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002882}
2883
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002884/*[clinic input]
2885_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002886
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002887 flags: int = 0
2888 /
2889
2890[clinic start generated code]*/
2891
2892static PyObject *
2893_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2894/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2895{
2896 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002897
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002898 ENTER_TCL
2899 rv = Tcl_DoOneEvent(flags);
2900 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002901 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002902}
2903
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002904/*[clinic input]
2905_tkinter.tkapp.quit
2906[clinic start generated code]*/
2907
Guido van Rossum062cfb01995-01-10 17:42:51 +00002908static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002909_tkinter_tkapp_quit_impl(TkappObject *self)
2910/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002911{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002912 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002913 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002914}
2915
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002916/*[clinic input]
2917_tkinter.tkapp.interpaddr
2918[clinic start generated code]*/
2919
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002920static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002921_tkinter_tkapp_interpaddr_impl(TkappObject *self)
2922/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002923{
Victor Stinnere1040e22013-09-05 00:22:24 +02002924 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002925}
2926
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002927/*[clinic input]
2928_tkinter.tkapp.loadtk
2929[clinic start generated code]*/
2930
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002931static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002932_tkinter_tkapp_loadtk_impl(TkappObject *self)
2933/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00002934{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002935 Tcl_Interp *interp = Tkapp_Interp(self);
2936 const char * _tk_exists = NULL;
2937 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002938
Guilherme Polob681df42009-02-09 22:33:59 +00002939#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002940 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2941 * first call failed.
2942 * To avoid the deadlock, we just refuse the second call through
2943 * a static variable.
2944 */
2945 if (tk_load_failed) {
2946 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2947 return NULL;
2948 }
Guilherme Polob681df42009-02-09 22:33:59 +00002949#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002950
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002951 /* We want to guard against calling Tk_Init() multiple times */
2952 CHECK_TCL_APPARTMENT;
2953 ENTER_TCL
2954 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2955 ENTER_OVERLAP
2956 if (err == TCL_ERROR) {
2957 /* This sets an exception, but we cannot return right
2958 away because we need to exit the overlap first. */
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002959 Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002960 } else {
2961 _tk_exists = Tkapp_Result(self);
2962 }
2963 LEAVE_OVERLAP_TCL
2964 if (err == TCL_ERROR) {
2965 return NULL;
2966 }
2967 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2968 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002969 PyErr_SetString(Tkinter_TclError,
2970 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002971#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002972 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002973#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002974 return NULL;
2975 }
2976 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002977 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002978}
Barry Warsawfa701a81997-01-16 00:15:11 +00002979
Martin v. Löwisffad6332002-11-26 09:28:05 +00002980static PyObject *
2981Tkapp_WantObjects(PyObject *self, PyObject *args)
2982{
2983
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002984 int wantobjects = -1;
2985 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2986 return NULL;
2987 if (wantobjects == -1)
2988 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2989 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002990
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002991 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002992}
2993
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002994/*[clinic input]
2995_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002996
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002997[clinic start generated code]*/
2998
2999static PyObject *
3000_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03003001/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003002{
3003 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003004
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003005 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003006}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003008
Guido van Rossum18468821994-06-20 07:49:28 +00003009/**** Tkapp Type Methods ****/
3010
3011static void
Fred Drake509d79a2000-07-08 04:04:38 +00003012Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003013{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003014 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003015 /*CHECK_TCL_APPARTMENT;*/
3016 ENTER_TCL
3017 Tcl_DeleteInterp(Tkapp_Interp(self));
3018 LEAVE_TCL
3019 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003020 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003021 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003022}
3023
Barry Warsawfa701a81997-01-16 00:15:11 +00003024
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003025
Guido van Rossum18468821994-06-20 07:49:28 +00003026/**** Tkinter Module ****/
3027
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003028typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003029 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003030 Py_ssize_t size; /* current size */
3031 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003032} FlattenContext;
3033
3034static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003035_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003036{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003037 /* expand tuple to hold (at least) size new items.
3038 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003039
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003040 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003041
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003042 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003043 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003044
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003045 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003046
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003047 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003048}
3049
3050static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003051_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003052{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003053 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003054
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003055 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003057 if (depth > 1000) {
3058 PyErr_SetString(PyExc_ValueError,
3059 "nesting too deep in _flatten");
3060 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003061 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3062 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003063 /* preallocate (assume no nesting) */
3064 if (context->size + size > context->maxsize &&
3065 !_bump(context, size))
3066 return 0;
3067 /* copy items to output tuple */
3068 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003069 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003070 if (PyList_Check(o) || PyTuple_Check(o)) {
3071 if (!_flatten1(context, o, depth + 1))
3072 return 0;
3073 } else if (o != Py_None) {
3074 if (context->size + 1 > context->maxsize &&
3075 !_bump(context, 1))
3076 return 0;
3077 Py_INCREF(o);
3078 PyTuple_SET_ITEM(context->tuple,
3079 context->size++, o);
3080 }
3081 }
3082 } else {
3083 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3084 return 0;
3085 }
3086 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003087}
3088
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003089/*[clinic input]
3090_tkinter._flatten
3091
3092 item: object
3093 /
3094
3095[clinic start generated code]*/
3096
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003097static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003098_tkinter__flatten(PyObject *module, PyObject *item)
3099/*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003100{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003101 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003102
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003103 context.maxsize = PySequence_Size(item);
3104 if (context.maxsize < 0)
3105 return NULL;
3106 if (context.maxsize == 0)
3107 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003109 context.tuple = PyTuple_New(context.maxsize);
3110 if (!context.tuple)
3111 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003112
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003113 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003114
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003115 if (!_flatten1(&context, item,0))
3116 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003118 if (_PyTuple_Resize(&context.tuple, context.size))
3119 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003120
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003121 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003122}
3123
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003124/*[clinic input]
3125_tkinter.create
3126
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003127 screenName: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003128 baseName: str = NULL
3129 className: str = "Tk"
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003130 interactive: bool(accept={int}) = False
3131 wantobjects: bool(accept={int}) = False
3132 wantTk: bool(accept={int}) = True
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003133 if false, then Tk_Init() doesn't get called
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003134 sync: bool(accept={int}) = False
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003135 if true, then pass -sync to wish
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003136 use: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003137 if not None, then pass -use to wish
3138 /
3139
3140[clinic start generated code]*/
3141
Guido van Rossum18468821994-06-20 07:49:28 +00003142static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003143_tkinter_create_impl(PyObject *module, const char *screenName,
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003144 const char *baseName, const char *className,
3145 int interactive, int wantobjects, int wantTk, int sync,
3146 const char *use)
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003147/*[clinic end generated code: output=e3315607648e6bb4 input=431907c134c80085]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003148{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003149 /* XXX baseName is not used anymore;
3150 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003151 CHECK_STRING_LENGTH(screenName);
3152 CHECK_STRING_LENGTH(baseName);
3153 CHECK_STRING_LENGTH(className);
3154 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003155
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003156 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003157 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003158 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003159}
3160
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003161/*[clinic input]
3162_tkinter.setbusywaitinterval
3163
3164 new_val: int
3165 /
3166
3167Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3168
3169It should be set to a divisor of the maximum time between frames in an animation.
3170[clinic start generated code]*/
3171
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003172static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003173_tkinter_setbusywaitinterval_impl(PyObject *module, int new_val)
3174/*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003175{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003176 if (new_val < 0) {
3177 PyErr_SetString(PyExc_ValueError,
3178 "busywaitinterval must be >= 0");
3179 return NULL;
3180 }
3181 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003182 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003183}
3184
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003185/*[clinic input]
3186_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003187
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003188Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3189[clinic start generated code]*/
3190
3191static int
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003192_tkinter_getbusywaitinterval_impl(PyObject *module)
3193/*[clinic end generated code: output=23b72d552001f5c7 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003194{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003195 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003196}
3197
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003198#include "clinic/_tkinter.c.h"
3199
3200static PyMethodDef Tktt_methods[] =
3201{
3202 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3203 {NULL, NULL}
3204};
3205
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003206static PyType_Slot Tktt_Type_slots[] = {
3207 {Py_tp_dealloc, Tktt_Dealloc},
3208 {Py_tp_repr, Tktt_Repr},
3209 {Py_tp_methods, Tktt_methods},
3210 {0, 0}
3211};
3212
3213static PyType_Spec Tktt_Type_spec = {
3214 "_tkinter.tktimertoken",
3215 sizeof(TkttObject),
3216 0,
3217 Py_TPFLAGS_DEFAULT,
3218 Tktt_Type_slots,
3219};
3220
3221
3222/**** Tkapp Method List ****/
3223
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003224static PyMethodDef Tkapp_methods[] =
3225{
3226 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3227 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3228 {"call", Tkapp_Call, METH_VARARGS},
3229 _TKINTER_TKAPP_EVAL_METHODDEF
3230 _TKINTER_TKAPP_EVALFILE_METHODDEF
3231 _TKINTER_TKAPP_RECORD_METHODDEF
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03003232 _TKINTER_TKAPP_ADDERRORINFO_METHODDEF
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003233 {"setvar", Tkapp_SetVar, METH_VARARGS},
3234 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3235 {"getvar", Tkapp_GetVar, METH_VARARGS},
3236 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3237 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3238 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3239 _TKINTER_TKAPP_GETINT_METHODDEF
3240 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3241 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3242 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3243 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3244 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3245 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3246 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3247 _TKINTER_TKAPP_SPLIT_METHODDEF
3248 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3249 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3250 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3251 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3252 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3253 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3254 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3255 _TKINTER_TKAPP_QUIT_METHODDEF
3256 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3257 _TKINTER_TKAPP_LOADTK_METHODDEF
3258 {NULL, NULL}
3259};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003260
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003261static PyType_Slot Tkapp_Type_slots[] = {
3262 {Py_tp_dealloc, Tkapp_Dealloc},
3263 {Py_tp_methods, Tkapp_methods},
3264 {0, 0}
3265};
3266
3267
3268static PyType_Spec Tkapp_Type_spec = {
3269 "_tkinter.tkapp",
3270 sizeof(TkappObject),
3271 0,
3272 Py_TPFLAGS_DEFAULT,
3273 Tkapp_Type_slots,
3274};
3275
Guido van Rossum18468821994-06-20 07:49:28 +00003276static PyMethodDef moduleMethods[] =
3277{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003278 _TKINTER__FLATTEN_METHODDEF
3279 _TKINTER_CREATE_METHODDEF
3280 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3281 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003282 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003283};
3284
Guido van Rossum7bf15641998-05-22 18:28:17 +00003285#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003286
3287static int stdin_ready = 0;
3288
Guido van Rossumad4db171998-06-13 13:56:28 +00003289#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003290static void
Fred Drake509d79a2000-07-08 04:04:38 +00003291MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003292{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003293 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003294}
Guido van Rossumad4db171998-06-13 13:56:28 +00003295#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003296
Guido van Rossum00d93061998-05-28 23:06:38 +00003297static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003298
Guido van Rossum18468821994-06-20 07:49:28 +00003299static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003300EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003301{
Guido van Rossumad4db171998-06-13 13:56:28 +00003302#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003303 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003304#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003305 PyEval_RestoreThread(event_tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003306 stdin_ready = 0;
3307 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003308#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003309 tfile = fileno(stdin);
3310 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003311#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003312 while (!errorInCmd && !stdin_ready) {
3313 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003314#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003315 if (_kbhit()) {
3316 stdin_ready = 1;
3317 break;
3318 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003319#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003320 Py_BEGIN_ALLOW_THREADS
3321 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3322 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003323
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003324 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003326 tcl_tstate = NULL;
3327 if(tcl_lock)PyThread_release_lock(tcl_lock);
3328 if (result == 0)
3329 Sleep(Tkinter_busywaitinterval);
3330 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003331
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003332 if (result < 0)
3333 break;
3334 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003335#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003336 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003337#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003338 if (errorInCmd) {
3339 errorInCmd = 0;
3340 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3341 excInCmd = valInCmd = trbInCmd = NULL;
3342 PyErr_Print();
3343 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003344 PyEval_SaveThread();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003345 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003346}
Guido van Rossum18468821994-06-20 07:49:28 +00003347
Guido van Rossum00d93061998-05-28 23:06:38 +00003348#endif
3349
Guido van Rossum7bf15641998-05-22 18:28:17 +00003350static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003351EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003352{
Guido van Rossum00d93061998-05-28 23:06:38 +00003353#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003354 if (PyOS_InputHook == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003355 event_tstate = PyThreadState_Get();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003356 PyOS_InputHook = EventHook;
3357 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003358#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003359}
3360
3361static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003362DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003363{
Guido van Rossum00d93061998-05-28 23:06:38 +00003364#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003365 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3366 PyOS_InputHook = NULL;
3367 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003368#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003369}
3370
Barry Warsawfa701a81997-01-16 00:15:11 +00003371
Martin v. Löwis1a214512008-06-11 05:26:20 +00003372static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003373 PyModuleDef_HEAD_INIT,
3374 "_tkinter",
3375 NULL,
3376 -1,
3377 moduleMethods,
3378 NULL,
3379 NULL,
3380 NULL,
3381 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003382};
3383
Mark Hammond62b1ab12002-07-23 06:31:15 +00003384PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003385PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003386{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003387 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003389 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003390 if (tcl_lock == NULL)
3391 return NULL;
Guido van Rossumae92f011996-08-21 19:03:36 +00003392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003393 m = PyModule_Create(&_tkintermodule);
3394 if (m == NULL)
3395 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003396
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003397 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3398 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003399 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003400 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003401 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003402 Py_INCREF(o);
3403 if (PyModule_AddObject(m, "TclError", o)) {
3404 Py_DECREF(o);
3405 Py_DECREF(m);
3406 return NULL;
3407 }
3408 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003409
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003410 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3411 Py_DECREF(m);
3412 return NULL;
3413 }
3414 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3415 Py_DECREF(m);
3416 return NULL;
3417 }
3418 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3419 Py_DECREF(m);
3420 return NULL;
3421 }
3422 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3423 Py_DECREF(m);
3424 return NULL;
3425 }
3426 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3427 Py_DECREF(m);
3428 return NULL;
3429 }
3430 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3431 Py_DECREF(m);
3432 return NULL;
3433 }
3434 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3435 Py_DECREF(m);
3436 return NULL;
3437 }
3438 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3439 Py_DECREF(m);
3440 return NULL;
3441 }
3442 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3443 Py_DECREF(m);
3444 return NULL;
3445 }
3446 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3447 Py_DECREF(m);
3448 return NULL;
3449 }
3450 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3451 Py_DECREF(m);
3452 return NULL;
3453 }
3454
3455 o = PyType_FromSpec(&Tkapp_Type_spec);
3456 if (o == NULL) {
3457 Py_DECREF(m);
3458 return NULL;
3459 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003460 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003461 if (PyModule_AddObject(m, "TkappType", o)) {
3462 Py_DECREF(o);
3463 Py_DECREF(m);
3464 return NULL;
3465 }
3466 Tkapp_Type = o;
3467
3468 o = PyType_FromSpec(&Tktt_Type_spec);
3469 if (o == NULL) {
3470 Py_DECREF(m);
3471 return NULL;
3472 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003473 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003474 if (PyModule_AddObject(m, "TkttType", o)) {
3475 Py_DECREF(o);
3476 Py_DECREF(m);
3477 return NULL;
3478 }
3479 Tktt_Type = o;
3480
3481 o = PyType_FromSpec(&PyTclObject_Type_spec);
3482 if (o == NULL) {
3483 Py_DECREF(m);
3484 return NULL;
3485 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003486 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003487 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3488 Py_DECREF(o);
3489 Py_DECREF(m);
3490 return NULL;
3491 }
3492 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003493
3494#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003495 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3496 * start waking up. Note that Tcl_FindExecutable will do this, this
3497 * code must be above it! The original warning from
3498 * tkMacOSXAppInit.c is copied below.
3499 *
3500 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3501 * Tcl interpreter for now. It probably should work to do this
3502 * in the other order, but for now it doesn't seem to.
3503 *
3504 */
3505 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003506#endif
3507
3508
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003509 /* This helps the dynamic loader; in Unicode aware Tcl versions
3510 it also helps Tcl find its encodings. */
3511 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3512 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003513 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003514 if (cexe) {
3515#ifdef MS_WINDOWS
3516 int set_var = 0;
3517 PyObject *str_path;
3518 wchar_t *wcs_path;
3519 DWORD ret;
3520
3521 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3522
3523 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3524 str_path = _get_tcl_lib_path();
3525 if (str_path == NULL && PyErr_Occurred()) {
3526 return NULL;
3527 }
3528 if (str_path != NULL) {
3529 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3530 if (wcs_path == NULL) {
3531 return NULL;
3532 }
3533 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3534 set_var = 1;
3535 }
3536 }
3537
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003538 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003539
3540 if (set_var) {
3541 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3542 PyMem_Free(wcs_path);
3543 }
3544#else
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003545 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003546#endif /* MS_WINDOWS */
3547 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003548 Py_XDECREF(cexe);
3549 Py_DECREF(uexe);
3550 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003551
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003552 if (PyErr_Occurred()) {
3553 Py_DECREF(m);
3554 return NULL;
3555 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003556
Guido van Rossum43ff8681998-07-14 18:02:13 +00003557#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003558 /* This was not a good idea; through <Destroy> bindings,
3559 Tcl_Finalize() may invoke Python code but at that point the
3560 interpreter and thread state have already been destroyed! */
3561 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003562#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003563 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003564}