blob: 93d4dbc5f659a04d31fc5b0c549606dc1c4ba5fe [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 *
Walter Dörwald6720d912007-07-12 12:12:25 +0000845PyTclObject_str(PyTclObject *self, void *ignored)
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{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300858 PyObject *repr, *str = PyTclObject_str(self, NULL);
859 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)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001104 Tcl_Obj *v = ((PyTclObject*)value)->value;
1105 Tcl_IncrRefCount(v);
1106 return v;
1107 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001108
1109 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001110 PyObject *v = PyObject_Str(value);
1111 if (!v)
1112 return 0;
1113 result = AsObj(v);
1114 Py_DECREF(v);
1115 return result;
1116 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001117}
1118
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001119static PyObject *
1120fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1121{
1122 int boolValue;
1123 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1124 return Tkinter_Error(tkapp);
1125 return PyBool_FromLong(boolValue);
1126}
1127
Martin v. Löwisffad6332002-11-26 09:28:05 +00001128static PyObject*
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001129fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1130{
1131 Tcl_WideInt wideValue;
1132 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001133 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1134 return PyLong_FromLongLong(wideValue);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001135 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1136 sizeof(wideValue),
1137 PY_LITTLE_ENDIAN,
1138 /* signed */ 1);
1139 }
1140 return NULL;
1141}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001142
1143#ifdef HAVE_LIBTOMMAMTH
1144static PyObject*
1145fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1146{
1147 mp_int bigValue;
1148 unsigned long numBytes;
1149 unsigned char *bytes;
1150 PyObject *res;
1151
1152 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1153 return Tkinter_Error(tkapp);
1154 numBytes = mp_unsigned_bin_size(&bigValue);
1155 bytes = PyMem_Malloc(numBytes);
1156 if (bytes == NULL) {
1157 mp_clear(&bigValue);
1158 return PyErr_NoMemory();
1159 }
1160 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1161 &numBytes) != MP_OKAY) {
1162 mp_clear(&bigValue);
1163 PyMem_Free(bytes);
1164 return PyErr_NoMemory();
1165 }
1166 res = _PyLong_FromByteArray(bytes, numBytes,
1167 /* big-endian */ 0,
1168 /* unsigned */ 0);
1169 PyMem_Free(bytes);
1170 if (res != NULL && bigValue.sign == MP_NEG) {
1171 PyObject *res2 = PyNumber_Negative(res);
1172 Py_DECREF(res);
1173 res = res2;
1174 }
1175 mp_clear(&bigValue);
1176 return res;
1177}
1178#endif
1179
Martin v. Löwisffad6332002-11-26 09:28:05 +00001180static PyObject*
1181FromObj(PyObject* tkapp, Tcl_Obj *value)
1182{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001183 PyObject *result = NULL;
1184 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001185 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001186
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001187 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001188 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001189 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001190
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001191 if (value->typePtr == app->BooleanType ||
1192 value->typePtr == app->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001193 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001194 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001195
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001196 if (value->typePtr == app->ByteArrayType) {
1197 int size;
1198 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1199 return PyBytes_FromStringAndSize(data, size);
1200 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001201
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001202 if (value->typePtr == app->DoubleType) {
1203 return PyFloat_FromDouble(value->internalRep.doubleValue);
1204 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001205
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001206 if (value->typePtr == app->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001207 long longValue;
1208 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1209 return PyLong_FromLong(longValue);
1210 /* If there is an error in the long conversion,
1211 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001212 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001213
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001214 if (value->typePtr == app->IntType ||
1215 value->typePtr == app->WideIntType) {
1216 result = fromWideIntObj(tkapp, value);
1217 if (result != NULL || PyErr_Occurred())
1218 return result;
1219 Tcl_ResetResult(interp);
1220 /* If there is an error in the wideInt conversion,
1221 fall through to bignum handling. */
1222 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001223
1224#ifdef HAVE_LIBTOMMAMTH
1225 if (value->typePtr == app->IntType ||
1226 value->typePtr == app->WideIntType ||
1227 value->typePtr == app->BignumType) {
1228 return fromBignumObj(tkapp, value);
1229 }
1230#endif
1231
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001232 if (value->typePtr == app->ListType) {
1233 int size;
1234 int i, status;
1235 PyObject *elem;
1236 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001237
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001238 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001239 if (status == TCL_ERROR)
1240 return Tkinter_Error(tkapp);
1241 result = PyTuple_New(size);
1242 if (!result)
1243 return NULL;
1244 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001245 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001246 if (status == TCL_ERROR) {
1247 Py_DECREF(result);
1248 return Tkinter_Error(tkapp);
1249 }
1250 elem = FromObj(tkapp, tcl_elem);
1251 if (!elem) {
1252 Py_DECREF(result);
1253 return NULL;
1254 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001255 PyTuple_SET_ITEM(result, i, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001256 }
1257 return result;
1258 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001260 if (value->typePtr == app->ProcBodyType) {
1261 /* fall through: return tcl object. */
1262 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001263
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001264 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001265 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001266 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001267 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001268 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001269
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001270#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001271 if (app->BooleanType == NULL &&
1272 strcmp(value->typePtr->name, "booleanString") == 0) {
1273 /* booleanString type is not registered in Tcl */
1274 app->BooleanType = value->typePtr;
1275 return fromBoolean(tkapp, value);
1276 }
1277#endif
1278
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001279#ifdef HAVE_LIBTOMMAMTH
1280 if (app->BignumType == NULL &&
1281 strcmp(value->typePtr->name, "bignum") == 0) {
1282 /* bignum type is not registered in Tcl */
1283 app->BignumType = value->typePtr;
1284 return fromBignumObj(tkapp, value);
1285 }
1286#endif
1287
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001288 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001289}
1290
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001291/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001292TCL_DECLARE_MUTEX(call_mutex)
1293
1294typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001295 Tcl_Event ev; /* Must be first */
1296 TkappObject *self;
1297 PyObject *args;
1298 int flags;
1299 PyObject **res;
1300 PyObject **exc_type, **exc_value, **exc_tb;
1301 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001302} Tkapp_CallEvent;
1303
1304void
1305Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001306{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001307 int i;
1308 for (i = 0; i < objc; i++)
1309 Tcl_DecrRefCount(objv[i]);
1310 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001311 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001312}
Guido van Rossum18468821994-06-20 07:49:28 +00001313
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001314/* Convert Python objects to Tcl objects. This must happen in the
1315 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001316
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001317static Tcl_Obj**
1318Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1319{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001320 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001321 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001322 if (args == NULL)
1323 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001324
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001325 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 objv[0] = AsObj(args);
Serhiy Storchaka0b3ec192017-03-23 17:53:47 +02001327 if (objv[0] == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001328 goto finally;
1329 objc = 1;
1330 Tcl_IncrRefCount(objv[0]);
1331 }
1332 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001333 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001334
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001335 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001336 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001337 PyErr_SetString(PyExc_OverflowError,
1338 PyTuple_Check(args) ? "tuple is too long" :
1339 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001340 return NULL;
1341 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001342 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 if (objv == NULL) {
1344 PyErr_NoMemory();
1345 objc = 0;
1346 goto finally;
1347 }
1348 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001351 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 if (v == Py_None) {
1353 objc = i;
1354 break;
1355 }
1356 objv[i] = AsObj(v);
1357 if (!objv[i]) {
1358 /* Reset objc, so it attempts to clear
1359 objects only up to i. */
1360 objc = i;
1361 goto finally;
1362 }
1363 Tcl_IncrRefCount(objv[i]);
1364 }
1365 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001366 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001367 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001368finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001369 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001370 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001371}
Guido van Rossum212643f1998-04-29 16:22:14 +00001372
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001373/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001374
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001375static PyObject*
1376Tkapp_CallResult(TkappObject *self)
1377{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001378 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001379 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001380 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001381 /* Not sure whether the IncrRef is necessary, but something
1382 may overwrite the interpreter result while we are
1383 converting it. */
1384 Tcl_IncrRefCount(value);
1385 res = FromObj((PyObject*)self, value);
1386 Tcl_DecrRefCount(value);
1387 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001388 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001389 }
1390 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001391}
Guido van Rossum632de272000-03-29 00:19:50 +00001392
Benjamin Peterson5879d412009-03-30 14:51:56 +00001393
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001394/* Tkapp_CallProc is the event procedure that is executed in the context of
1395 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1396 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001397
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001398static int
1399Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1400{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001401 Tcl_Obj *objStore[ARGSZ];
1402 Tcl_Obj **objv;
1403 int objc;
1404 int i;
1405 ENTER_PYTHON
1406 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1407 if (!objv) {
1408 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1409 *(e->res) = NULL;
1410 }
1411 LEAVE_PYTHON
1412 if (!objv)
1413 goto done;
1414 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1415 ENTER_PYTHON
1416 if (i == TCL_ERROR) {
1417 *(e->res) = NULL;
1418 *(e->exc_type) = NULL;
1419 *(e->exc_tb) = NULL;
1420 *(e->exc_value) = PyObject_CallFunction(
1421 Tkinter_TclError, "s",
1422 Tcl_GetStringResult(e->self->interp));
1423 }
1424 else {
1425 *(e->res) = Tkapp_CallResult(e->self);
1426 }
1427 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001429 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001430done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001431 /* Wake up calling thread. */
1432 Tcl_MutexLock(&call_mutex);
1433 Tcl_ConditionNotify(e->done);
1434 Tcl_MutexUnlock(&call_mutex);
1435 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001436}
1437
Benjamin Peterson5879d412009-03-30 14:51:56 +00001438
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001439/* This is the main entry point for calling a Tcl command.
1440 It supports three cases, with regard to threading:
1441 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1442 the context of the calling thread.
1443 2. Tcl is threaded, caller of the command is in the interpreter thread:
1444 Execute the command in the calling thread. Since the Tcl lock will
1445 not be used, we can merge that with case 1.
1446 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1447 the interpreter thread. Allocation of Tcl objects needs to occur in the
1448 interpreter thread, so we ship the PyObject* args to the target thread,
1449 and perform processing there. */
1450
1451static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001452Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001453{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001454 Tcl_Obj *objStore[ARGSZ];
1455 Tcl_Obj **objv = NULL;
1456 int objc, i;
1457 PyObject *res = NULL;
1458 TkappObject *self = (TkappObject*)selfptr;
1459 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001461 /* If args is a single tuple, replace with contents of tuple */
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001462 if (PyTuple_GET_SIZE(args) == 1) {
1463 PyObject *item = PyTuple_GET_ITEM(args, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001464 if (PyTuple_Check(item))
1465 args = item;
1466 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001467 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1468 /* We cannot call the command directly. Instead, we must
1469 marshal the parameters to the interpreter thread. */
1470 Tkapp_CallEvent *ev;
1471 Tcl_Condition cond = NULL;
1472 PyObject *exc_type, *exc_value, *exc_tb;
1473 if (!WaitForMainloop(self))
1474 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001475 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1476 if (ev == NULL) {
1477 PyErr_NoMemory();
1478 return NULL;
1479 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001480 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1481 ev->self = self;
1482 ev->args = args;
1483 ev->res = &res;
1484 ev->exc_type = &exc_type;
1485 ev->exc_value = &exc_value;
1486 ev->exc_tb = &exc_tb;
1487 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001488
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001489 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001490
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001491 if (res == NULL) {
1492 if (exc_type)
1493 PyErr_Restore(exc_type, exc_value, exc_tb);
1494 else
1495 PyErr_SetObject(Tkinter_TclError, exc_value);
1496 }
1497 Tcl_ConditionFinalize(&cond);
1498 }
1499 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001500 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001501
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001502 objv = Tkapp_CallArgs(args, objStore, &objc);
1503 if (!objv)
1504 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001506 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001508 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001512 if (i == TCL_ERROR)
1513 Tkinter_Error(selfptr);
1514 else
1515 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001517 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001518
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001519 Tkapp_CallDeallocArgs(objv, objStore, objc);
1520 }
1521 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001522}
1523
1524
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001525/*[clinic input]
1526_tkinter.tkapp.eval
1527
1528 script: str
1529 /
1530
1531[clinic start generated code]*/
1532
Barry Warsawfa701a81997-01-16 00:15:11 +00001533static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001534_tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1535/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001536{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001537 PyObject *res = NULL;
1538 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001539
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001540 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001542
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001543 ENTER_TCL
1544 err = Tcl_Eval(Tkapp_Interp(self), script);
1545 ENTER_OVERLAP
1546 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001547 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001548 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001549 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 LEAVE_OVERLAP_TCL
1551 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001552}
1553
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001554/*[clinic input]
1555_tkinter.tkapp.evalfile
1556
1557 fileName: str
1558 /
1559
1560[clinic start generated code]*/
1561
Guido van Rossum18468821994-06-20 07:49:28 +00001562static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001563_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1564/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001565{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566 PyObject *res = NULL;
1567 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001568
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001569 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001570 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001571
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001572 ENTER_TCL
1573 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1574 ENTER_OVERLAP
1575 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001576 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001577 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001578 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001579 LEAVE_OVERLAP_TCL
1580 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001581}
1582
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001583/*[clinic input]
1584_tkinter.tkapp.record
1585
1586 script: str
1587 /
1588
1589[clinic start generated code]*/
1590
Guido van Rossum18468821994-06-20 07:49:28 +00001591static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001592_tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1593/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001594{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001595 PyObject *res = NULL;
1596 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001597
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001598 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001599 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001601 ENTER_TCL
1602 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1603 ENTER_OVERLAP
1604 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001605 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001606 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001607 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001608 LEAVE_OVERLAP_TCL
1609 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001610}
1611
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001612/*[clinic input]
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001613_tkinter.tkapp.adderrorinfo
Guido van Rossum18468821994-06-20 07:49:28 +00001614
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001615 msg: str
1616 /
1617
1618[clinic start generated code]*/
1619
1620static PyObject *
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001621_tkinter_tkapp_adderrorinfo_impl(TkappObject *self, const char *msg)
1622/*[clinic end generated code: output=52162eaca2ee53cb input=f4b37aec7c7e8c77]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001623{
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001624 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001625 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001626
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001627 ENTER_TCL
1628 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1629 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001630
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001631 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001632}
1633
Barry Warsawfa701a81997-01-16 00:15:11 +00001634
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001635
Guido van Rossum18468821994-06-20 07:49:28 +00001636/** Tcl Variable **/
1637
Benjamin Peterson5879d412009-03-30 14:51:56 +00001638typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1639
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001640TCL_DECLARE_MUTEX(var_mutex)
1641
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001642typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001643 Tcl_Event ev; /* must be first */
1644 PyObject *self;
1645 PyObject *args;
1646 int flags;
1647 EventFunc func;
1648 PyObject **res;
1649 PyObject **exc_type;
1650 PyObject **exc_val;
1651 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001652} VarEvent;
1653
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001654/*[python]
1655
1656class varname_converter(CConverter):
1657 type = 'const char *'
1658 converter = 'varname_converter'
1659
1660[python]*/
1661/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1662
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001663static int
1664varname_converter(PyObject *in, void *_out)
1665{
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +02001666 const char *s;
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001667 const char **out = (const char**)_out;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001668 if (PyBytes_Check(in)) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001669 if (PyBytes_GET_SIZE(in) > INT_MAX) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001670 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1671 return 0;
1672 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001673 s = PyBytes_AS_STRING(in);
1674 if (strlen(s) != (size_t)PyBytes_GET_SIZE(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001675 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001676 return 0;
1677 }
1678 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001679 return 1;
1680 }
1681 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001682 Py_ssize_t size;
1683 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001684 if (s == NULL) {
1685 return 0;
1686 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001687 if (size > INT_MAX) {
1688 PyErr_SetString(PyExc_OverflowError, "string is too long");
1689 return 0;
1690 }
Victor Stinner706768c2014-08-16 01:03:39 +02001691 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001692 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001693 return 0;
1694 }
1695 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001696 return 1;
1697 }
1698 if (PyTclObject_Check(in)) {
1699 *out = PyTclObject_TclString(in);
1700 return 1;
1701 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001702 PyErr_Format(PyExc_TypeError,
1703 "must be str, bytes or Tcl_Obj, not %.50s",
1704 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001705 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001706}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001707
Benjamin Peterson5879d412009-03-30 14:51:56 +00001708
Martin v. Löwis59683e82008-06-13 07:50:45 +00001709static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001710var_perform(VarEvent *ev)
1711{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001712 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1713 if (!*(ev->res)) {
1714 PyObject *exc, *val, *tb;
1715 PyErr_Fetch(&exc, &val, &tb);
1716 PyErr_NormalizeException(&exc, &val, &tb);
1717 *(ev->exc_type) = exc;
1718 *(ev->exc_val) = val;
Serhiy Storchaka3ec5f422016-10-28 12:14:34 +03001719 Py_XDECREF(tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001720 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001721
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001722}
1723
1724static int
1725var_proc(VarEvent* ev, int flags)
1726{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001727 ENTER_PYTHON
1728 var_perform(ev);
1729 Tcl_MutexLock(&var_mutex);
1730 Tcl_ConditionNotify(ev->cond);
1731 Tcl_MutexUnlock(&var_mutex);
1732 LEAVE_PYTHON
1733 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001734}
1735
Benjamin Peterson5879d412009-03-30 14:51:56 +00001736
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001737static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001738var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001739{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001740 TkappObject *self = (TkappObject*)selfptr;
1741 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001742 VarEvent *ev;
1743 PyObject *res, *exc_type, *exc_val;
1744 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001745
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001746 /* The current thread is not the interpreter thread. Marshal
1747 the call to the interpreter thread, then wait for
1748 completion. */
1749 if (!WaitForMainloop(self))
1750 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001751
Serhiy Storchaka07940882014-09-11 10:38:54 +03001752 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1753 if (ev == NULL) {
1754 PyErr_NoMemory();
1755 return NULL;
1756 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001757 ev->self = selfptr;
1758 ev->args = args;
1759 ev->flags = flags;
1760 ev->func = func;
1761 ev->res = &res;
1762 ev->exc_type = &exc_type;
1763 ev->exc_val = &exc_val;
1764 ev->cond = &cond;
1765 ev->ev.proc = (Tcl_EventProc*)var_proc;
1766 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1767 Tcl_ConditionFinalize(&cond);
1768 if (!res) {
1769 PyErr_SetObject(exc_type, exc_val);
1770 Py_DECREF(exc_type);
1771 Py_DECREF(exc_val);
1772 return NULL;
1773 }
1774 return res;
1775 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001776 /* Tcl is not threaded, or this is the interpreter thread. */
1777 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001778}
1779
Guido van Rossum18468821994-06-20 07:49:28 +00001780static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001781SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001782{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001783 const char *name1, *name2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001784 PyObject *newValue;
1785 PyObject *res = NULL;
1786 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001787
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001788 switch (PyTuple_GET_SIZE(args)) {
1789 case 2:
1790 if (!PyArg_ParseTuple(args, "O&O:setvar",
1791 varname_converter, &name1, &newValue))
1792 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001793 /* XXX Acquire tcl lock??? */
1794 newval = AsObj(newValue);
1795 if (newval == NULL)
1796 return NULL;
1797 ENTER_TCL
1798 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1799 newval, flags);
1800 ENTER_OVERLAP
1801 if (!ok)
1802 Tkinter_Error(self);
1803 else {
1804 res = Py_None;
1805 Py_INCREF(res);
1806 }
1807 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001808 break;
1809 case 3:
1810 if (!PyArg_ParseTuple(args, "ssO:setvar",
1811 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001812 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001813 CHECK_STRING_LENGTH(name1);
1814 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001815 /* XXX must hold tcl lock already??? */
1816 newval = AsObj(newValue);
1817 ENTER_TCL
1818 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1819 ENTER_OVERLAP
1820 if (!ok)
1821 Tkinter_Error(self);
1822 else {
1823 res = Py_None;
1824 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001825 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001826 LEAVE_OVERLAP_TCL
1827 break;
1828 default:
1829 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1830 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001831 }
1832 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001833}
1834
1835static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001836Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001837{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001838 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001839}
1840
1841static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001842Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001843{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001844 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001845}
1846
Barry Warsawfa701a81997-01-16 00:15:11 +00001847
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001848
Guido van Rossum18468821994-06-20 07:49:28 +00001849static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001850GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001851{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001852 const char *name1, *name2=NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001853 PyObject *res = NULL;
1854 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001855
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001856 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1857 varname_converter, &name1, &name2))
1858 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001859
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001860 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001861 ENTER_TCL
1862 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1863 ENTER_OVERLAP
1864 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001865 PyErr_SetString(Tkinter_TclError,
1866 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001867 } else {
1868 if (((TkappObject*)self)->wantobjects) {
1869 res = FromObj(self, tres);
1870 }
1871 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001872 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001873 }
1874 }
1875 LEAVE_OVERLAP_TCL
1876 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001877}
1878
1879static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001880Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001881{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001882 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001883}
1884
1885static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001886Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001887{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001888 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001889}
1890
Barry Warsawfa701a81997-01-16 00:15:11 +00001891
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001892
Guido van Rossum18468821994-06-20 07:49:28 +00001893static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001894UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001895{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001896 char *name1, *name2=NULL;
1897 int code;
1898 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001899
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001900 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1901 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001902
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001903 CHECK_STRING_LENGTH(name1);
1904 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001905 ENTER_TCL
1906 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1907 ENTER_OVERLAP
1908 if (code == TCL_ERROR)
1909 res = Tkinter_Error(self);
1910 else {
1911 Py_INCREF(Py_None);
1912 res = Py_None;
1913 }
1914 LEAVE_OVERLAP_TCL
1915 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001916}
1917
1918static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001919Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001920{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001921 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001922}
1923
1924static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001925Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001926{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001927 return var_invoke(UnsetVar, self, args,
1928 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001929}
1930
Barry Warsawfa701a81997-01-16 00:15:11 +00001931
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001932
Guido van Rossum18468821994-06-20 07:49:28 +00001933/** Tcl to Python **/
1934
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001935/*[clinic input]
1936_tkinter.tkapp.getint
1937
1938 arg: object
1939 /
1940
1941[clinic start generated code]*/
1942
Guido van Rossum18468821994-06-20 07:49:28 +00001943static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001944_tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
1945/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001946{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001947 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001948 Tcl_Obj *value;
1949 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00001950
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001951 if (PyLong_Check(arg)) {
1952 Py_INCREF(arg);
1953 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001954 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001955
Serhiy Storchaka645058d2015-05-06 14:00:04 +03001956 if (PyTclObject_Check(arg)) {
1957 value = ((PyTclObject*)arg)->value;
1958 Tcl_IncrRefCount(value);
1959 }
1960 else {
1961 if (!PyArg_Parse(arg, "s:getint", &s))
1962 return NULL;
1963 CHECK_STRING_LENGTH(s);
1964 value = Tcl_NewStringObj(s, -1);
1965 if (value == NULL)
1966 return Tkinter_Error((PyObject *)self);
1967 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001968 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
1969 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
1970
1971 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
1972 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
1973 */
1974#ifdef HAVE_LIBTOMMAMTH
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001975 result = fromBignumObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001976#else
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001977 result = fromWideIntObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001978#endif
1979 Tcl_DecrRefCount(value);
1980 if (result != NULL || PyErr_Occurred())
1981 return result;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001982 return Tkinter_Error((PyObject *)self);
Guido van Rossum18468821994-06-20 07:49:28 +00001983}
1984
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001985/*[clinic input]
1986_tkinter.tkapp.getdouble
1987
1988 arg: object
1989 /
1990
1991[clinic start generated code]*/
1992
Guido van Rossum18468821994-06-20 07:49:28 +00001993static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001994_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
1995/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001996{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001997 char *s;
1998 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001999
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002000 if (PyFloat_Check(arg)) {
2001 Py_INCREF(arg);
2002 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002003 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002004
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002005 if (PyNumber_Check(arg)) {
2006 return PyNumber_Float(arg);
2007 }
2008
2009 if (PyTclObject_Check(arg)) {
2010 if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
2011 ((PyTclObject*)arg)->value,
2012 &v) == TCL_ERROR)
2013 return Tkinter_Error((PyObject *)self);
2014 return PyFloat_FromDouble(v);
2015 }
2016
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002017 if (!PyArg_Parse(arg, "s:getdouble", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002018 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002019 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002020 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002021 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002022 return PyFloat_FromDouble(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002023}
2024
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002025/*[clinic input]
2026_tkinter.tkapp.getboolean
2027
2028 arg: object
2029 /
2030
2031[clinic start generated code]*/
2032
Guido van Rossum18468821994-06-20 07:49:28 +00002033static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002034_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
2035/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002036{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002037 char *s;
2038 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002039
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002040 if (PyLong_Check(arg)) { /* int or bool */
2041 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002042 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002043
2044 if (PyTclObject_Check(arg)) {
2045 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2046 ((PyTclObject*)arg)->value,
2047 &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002048 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002049 return PyBool_FromLong(v);
2050 }
2051
2052 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002053 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002054 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002055 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002056 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002057 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002058}
2059
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002060/*[clinic input]
2061_tkinter.tkapp.exprstring
2062
2063 s: str
2064 /
2065
2066[clinic start generated code]*/
2067
Guido van Rossum18468821994-06-20 07:49:28 +00002068static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002069_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2070/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002071{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002072 PyObject *res = NULL;
2073 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002074
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002075 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002076 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002077
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002078 ENTER_TCL
2079 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2080 ENTER_OVERLAP
2081 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002082 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002083 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002084 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002085 LEAVE_OVERLAP_TCL
2086 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002087}
2088
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002089/*[clinic input]
2090_tkinter.tkapp.exprlong
2091
2092 s: str
2093 /
2094
2095[clinic start generated code]*/
2096
Guido van Rossum18468821994-06-20 07:49:28 +00002097static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002098_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2099/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002100{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002101 PyObject *res = NULL;
2102 int retval;
2103 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002104
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002105 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002106 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002107
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002108 ENTER_TCL
2109 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2110 ENTER_OVERLAP
2111 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002112 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002113 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002114 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115 LEAVE_OVERLAP_TCL
2116 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002117}
2118
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002119/*[clinic input]
2120_tkinter.tkapp.exprdouble
2121
2122 s: str
2123 /
2124
2125[clinic start generated code]*/
2126
Guido van Rossum18468821994-06-20 07:49:28 +00002127static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002128_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2129/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002130{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002131 PyObject *res = NULL;
2132 double v;
2133 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002134
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002135 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002136 CHECK_TCL_APPARTMENT;
2137 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2138 ENTER_TCL
2139 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2140 ENTER_OVERLAP
2141 PyFPE_END_PROTECT(retval)
2142 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002143 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002144 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002145 res = PyFloat_FromDouble(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002146 LEAVE_OVERLAP_TCL
2147 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002148}
2149
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002150/*[clinic input]
2151_tkinter.tkapp.exprboolean
2152
2153 s: str
2154 /
2155
2156[clinic start generated code]*/
2157
Guido van Rossum18468821994-06-20 07:49:28 +00002158static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002159_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2160/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002161{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002162 PyObject *res = NULL;
2163 int retval;
2164 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002165
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002166 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002167 CHECK_TCL_APPARTMENT;
2168 ENTER_TCL
2169 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2170 ENTER_OVERLAP
2171 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002172 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002173 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002174 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002175 LEAVE_OVERLAP_TCL
2176 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002177}
2178
Barry Warsawfa701a81997-01-16 00:15:11 +00002179
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002180
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002181/*[clinic input]
2182_tkinter.tkapp.splitlist
2183
2184 arg: object
2185 /
2186
2187[clinic start generated code]*/
2188
Guido van Rossum18468821994-06-20 07:49:28 +00002189static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002190_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2191/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002192{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002193 char *list;
2194 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002195 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002196 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002198
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002199 if (PyTclObject_Check(arg)) {
2200 int objc;
2201 Tcl_Obj **objv;
2202 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2203 ((PyTclObject*)arg)->value,
2204 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002205 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002206 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002207 if (!(v = PyTuple_New(objc)))
2208 return NULL;
2209 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002210 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002211 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002212 Py_DECREF(v);
2213 return NULL;
2214 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002215 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002216 }
2217 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002218 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002219 if (PyTuple_Check(arg)) {
2220 Py_INCREF(arg);
2221 return arg;
2222 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002223 if (PyList_Check(arg)) {
2224 return PySequence_Tuple(arg);
2225 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002226
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002227 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002228 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002229
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002230 if (strlen(list) >= INT_MAX) {
2231 PyErr_SetString(PyExc_OverflowError, "string is too long");
2232 PyMem_Free(list);
2233 return NULL;
2234 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002235 if (Tcl_SplitList(Tkapp_Interp(self), list,
2236 &argc, &argv) == TCL_ERROR) {
2237 PyMem_Free(list);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002238 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002239 }
Guido van Rossum18468821994-06-20 07:49:28 +00002240
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002241 if (!(v = PyTuple_New(argc)))
2242 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002243
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002244 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002245 PyObject *s = unicodeFromTclString(argv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002246 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002247 Py_DECREF(v);
2248 v = NULL;
2249 goto finally;
2250 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002251 PyTuple_SET_ITEM(v, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002252 }
Guido van Rossum18468821994-06-20 07:49:28 +00002253
Barry Warsawfa701a81997-01-16 00:15:11 +00002254 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002255 ckfree(FREECAST argv);
2256 PyMem_Free(list);
2257 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002258}
2259
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002260/*[clinic input]
2261_tkinter.tkapp.split
2262
2263 arg: object
2264 /
2265
2266[clinic start generated code]*/
2267
Guido van Rossum18468821994-06-20 07:49:28 +00002268static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002269_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2270/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002271{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002272 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002273 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002274
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002275 if (PyTclObject_Check(arg)) {
2276 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2277 int objc;
2278 Tcl_Obj **objv;
2279 int i;
2280 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2281 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002282 return FromObj((PyObject*)self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002283 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002284 if (objc == 0)
2285 return PyUnicode_FromString("");
2286 if (objc == 1)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002287 return FromObj((PyObject*)self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002288 if (!(v = PyTuple_New(objc)))
2289 return NULL;
2290 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002291 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002292 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002293 Py_DECREF(v);
2294 return NULL;
2295 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002296 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002297 }
2298 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002300 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002301 return SplitObj(arg);
2302
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002303 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002304 return NULL;
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002305 if (strlen(list) >= INT_MAX) {
2306 PyErr_SetString(PyExc_OverflowError, "string is too long");
2307 PyMem_Free(list);
2308 return NULL;
2309 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002310 v = Split(list);
2311 PyMem_Free(list);
2312 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002313}
2314
Barry Warsawfa701a81997-01-16 00:15:11 +00002315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002316
Guido van Rossum18468821994-06-20 07:49:28 +00002317/** Tcl Command **/
2318
Guido van Rossum00d93061998-05-28 23:06:38 +00002319/* Client data struct */
2320typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002321 PyObject *self;
2322 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002323} PythonCmd_ClientData;
2324
2325static int
Fred Drake509d79a2000-07-08 04:04:38 +00002326PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002327{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002328 errorInCmd = 1;
2329 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2330 LEAVE_PYTHON
2331 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002332}
2333
Guido van Rossum18468821994-06-20 07:49:28 +00002334/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002335 * function or method.
2336 */
Guido van Rossum18468821994-06-20 07:49:28 +00002337static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002338PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002339{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002340 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002341 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002342 int i, rv;
2343 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002345 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002346
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002347 /* TBD: no error checking here since we know, via the
2348 * Tkapp_CreateCommand() that the client data is a two-tuple
2349 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002350 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002352 /* Create argument list (argv1, ..., argvN) */
2353 if (!(arg = PyTuple_New(argc - 1)))
2354 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002356 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002357 PyObject *s = unicodeFromTclString(argv[i + 1]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002358 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002359 Py_DECREF(arg);
2360 return PythonCmd_Error(interp);
2361 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002362 PyTuple_SET_ITEM(arg, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002363 }
INADA Naoki72dccde2017-02-16 09:26:01 +09002364 res = PyObject_Call(func, arg, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002365 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002366
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002367 if (res == NULL)
2368 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002369
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002370 obj_res = AsObj(res);
2371 if (obj_res == NULL) {
2372 Py_DECREF(res);
2373 return PythonCmd_Error(interp);
2374 }
2375 else {
2376 Tcl_SetObjResult(interp, obj_res);
2377 rv = TCL_OK;
2378 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002380 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002382 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002384 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002385}
2386
2387static void
Fred Drake509d79a2000-07-08 04:04:38 +00002388PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002389{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002390 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002392 ENTER_PYTHON
2393 Py_XDECREF(data->self);
2394 Py_XDECREF(data->func);
2395 PyMem_DEL(data);
2396 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002397}
2398
Barry Warsawfa701a81997-01-16 00:15:11 +00002399
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002400
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002401
2402TCL_DECLARE_MUTEX(command_mutex)
2403
2404typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002405 Tcl_Event ev;
2406 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002407 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002408 int create;
2409 int *status;
2410 ClientData *data;
2411 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002412} CommandEvent;
2413
2414static int
2415Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002416{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002417 if (ev->create)
2418 *ev->status = Tcl_CreateCommand(
2419 ev->interp, ev->name, PythonCmd,
2420 ev->data, PythonCmdDelete) == NULL;
2421 else
2422 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2423 Tcl_MutexLock(&command_mutex);
2424 Tcl_ConditionNotify(ev->done);
2425 Tcl_MutexUnlock(&command_mutex);
2426 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002427}
2428
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002429/*[clinic input]
2430_tkinter.tkapp.createcommand
2431
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002432 name: str
2433 func: object
2434 /
2435
2436[clinic start generated code]*/
2437
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002438static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002439_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2440 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002441/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002442{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002443 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002444 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002445
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002446 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002447 if (!PyCallable_Check(func)) {
2448 PyErr_SetString(PyExc_TypeError, "command not callable");
2449 return NULL;
2450 }
Guido van Rossum18468821994-06-20 07:49:28 +00002451
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002452 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2453 !WaitForMainloop(self))
2454 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002456 data = PyMem_NEW(PythonCmd_ClientData, 1);
2457 if (!data)
2458 return PyErr_NoMemory();
2459 Py_INCREF(self);
2460 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002461 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002462 data->func = func;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002463 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2464 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002465 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2466 if (ev == NULL) {
2467 PyErr_NoMemory();
2468 PyMem_DEL(data);
2469 return NULL;
2470 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2472 ev->interp = self->interp;
2473 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002474 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002475 ev->data = (ClientData)data;
2476 ev->status = &err;
2477 ev->done = &cond;
2478 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2479 Tcl_ConditionFinalize(&cond);
2480 }
2481 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002482 {
2483 ENTER_TCL
2484 err = Tcl_CreateCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002485 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002486 (ClientData)data, PythonCmdDelete) == NULL;
2487 LEAVE_TCL
2488 }
2489 if (err) {
2490 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2491 PyMem_DEL(data);
2492 return NULL;
2493 }
Guido van Rossum18468821994-06-20 07:49:28 +00002494
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002495 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002496}
2497
Barry Warsawfa701a81997-01-16 00:15:11 +00002498
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002499
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002500/*[clinic input]
2501_tkinter.tkapp.deletecommand
2502
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002503 name: str
2504 /
2505
2506[clinic start generated code]*/
2507
Guido van Rossum18468821994-06-20 07:49:28 +00002508static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002509_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002510/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002511{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002512 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002513
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002514 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002515
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002516 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2517 Tcl_Condition cond = NULL;
2518 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002519 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2520 if (ev == NULL) {
2521 PyErr_NoMemory();
2522 return NULL;
2523 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002524 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2525 ev->interp = self->interp;
2526 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002527 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002528 ev->status = &err;
2529 ev->done = &cond;
2530 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2531 &command_mutex);
2532 Tcl_ConditionFinalize(&cond);
2533 }
2534 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002535 {
2536 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002537 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002538 LEAVE_TCL
2539 }
2540 if (err == -1) {
2541 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2542 return NULL;
2543 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002544 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002545}
2546
Barry Warsawfa701a81997-01-16 00:15:11 +00002547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002548
Guido van Rossum00d93061998-05-28 23:06:38 +00002549#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002550/** File Handler **/
2551
Guido van Rossum00d93061998-05-28 23:06:38 +00002552typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002553 PyObject *func;
2554 PyObject *file;
2555 int id;
2556 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002557} FileHandler_ClientData;
2558
2559static FileHandler_ClientData *HeadFHCD;
2560
2561static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002562NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002563{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002564 FileHandler_ClientData *p;
2565 p = PyMem_NEW(FileHandler_ClientData, 1);
2566 if (p != NULL) {
2567 Py_XINCREF(func);
2568 Py_XINCREF(file);
2569 p->func = func;
2570 p->file = file;
2571 p->id = id;
2572 p->next = HeadFHCD;
2573 HeadFHCD = p;
2574 }
2575 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002576}
2577
2578static void
Fred Drake509d79a2000-07-08 04:04:38 +00002579DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002580{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002581 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002582
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002583 pp = &HeadFHCD;
2584 while ((p = *pp) != NULL) {
2585 if (p->id == id) {
2586 *pp = p->next;
2587 Py_XDECREF(p->func);
2588 Py_XDECREF(p->file);
2589 PyMem_DEL(p);
2590 }
2591 else
2592 pp = &p->next;
2593 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002594}
2595
Guido van Rossuma597dde1995-01-10 20:56:29 +00002596static void
Fred Drake509d79a2000-07-08 04:04:38 +00002597FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002598{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002599 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
INADA Naoki72dccde2017-02-16 09:26:01 +09002600 PyObject *func, *file, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002602 ENTER_PYTHON
2603 func = data->func;
2604 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002605
INADA Naoki72dccde2017-02-16 09:26:01 +09002606 res = PyObject_CallFunction(func, "Oi", file, mask);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002607 if (res == NULL) {
2608 errorInCmd = 1;
2609 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2610 }
2611 Py_XDECREF(res);
2612 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002613}
2614
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002615/*[clinic input]
2616_tkinter.tkapp.createfilehandler
2617
2618 file: object
2619 mask: int
2620 func: object
2621 /
2622
2623[clinic start generated code]*/
2624
Guido van Rossum18468821994-06-20 07:49:28 +00002625static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002626_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2627 int mask, PyObject *func)
2628/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002629{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002630 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002631 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002633 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002634
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002635 tfile = PyObject_AsFileDescriptor(file);
2636 if (tfile < 0)
2637 return NULL;
2638 if (!PyCallable_Check(func)) {
2639 PyErr_SetString(PyExc_TypeError, "bad argument list");
2640 return NULL;
2641 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002643 data = NewFHCD(func, file, tfile);
2644 if (data == NULL)
2645 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002647 /* Ought to check for null Tcl_File object... */
2648 ENTER_TCL
2649 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2650 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002651 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002652}
2653
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002654/*[clinic input]
2655_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002656
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002657 file: object
2658 /
2659
2660[clinic start generated code]*/
2661
2662static PyObject *
2663_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2664/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2665{
2666 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002668 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002670 tfile = PyObject_AsFileDescriptor(file);
2671 if (tfile < 0)
2672 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002674 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 /* Ought to check for null Tcl_File object... */
2677 ENTER_TCL
2678 Tcl_DeleteFileHandler(tfile);
2679 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002680 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002681}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002682#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002684
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002685/**** Tktt Object (timer token) ****/
2686
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002687static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002688
Guido van Rossum00d93061998-05-28 23:06:38 +00002689typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002690 PyObject_HEAD
2691 Tcl_TimerToken token;
2692 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002693} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002694
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002695/*[clinic input]
2696_tkinter.tktimertoken.deletetimerhandler
2697
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002698[clinic start generated code]*/
2699
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002700static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002701_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002702/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002703{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002704 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002705 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002706
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002707 if (v->token != NULL) {
2708 Tcl_DeleteTimerHandler(v->token);
2709 v->token = NULL;
2710 }
2711 if (func != NULL) {
2712 v->func = NULL;
2713 Py_DECREF(func);
2714 Py_DECREF(v); /* See Tktt_New() */
2715 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002716 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002717}
2718
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002719static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002720Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002721{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002722 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002723
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002724 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002725 if (v == NULL)
2726 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002727 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002728
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002729 Py_INCREF(func);
2730 v->token = NULL;
2731 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002732
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002733 /* Extra reference, deleted when called or when handler is deleted */
2734 Py_INCREF(v);
2735 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002736}
2737
2738static void
Fred Drake509d79a2000-07-08 04:04:38 +00002739Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002740{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741 TkttObject *v = (TkttObject *)self;
2742 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002743 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002744
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002745 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002746
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002747 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002748 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002749}
2750
Guido van Rossum597ac201998-05-12 14:36:19 +00002751static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002752Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002753{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002754 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002755 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2756 v,
2757 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002758}
2759
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002760/** Timer Handler **/
2761
2762static void
Fred Drake509d79a2000-07-08 04:04:38 +00002763TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002764{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002765 TkttObject *v = (TkttObject *)clientData;
2766 PyObject *func = v->func;
2767 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002769 if (func == NULL)
2770 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002771
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002772 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002773
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002774 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002775
INADA Naoki72dccde2017-02-16 09:26:01 +09002776 res = _PyObject_CallNoArg(func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002777 Py_DECREF(func);
2778 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002779
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002780 if (res == NULL) {
2781 errorInCmd = 1;
2782 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2783 }
2784 else
2785 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002786
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002787 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002788}
2789
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002790/*[clinic input]
2791_tkinter.tkapp.createtimerhandler
2792
2793 milliseconds: int
2794 func: object
2795 /
2796
2797[clinic start generated code]*/
2798
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002799static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002800_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2801 PyObject *func)
2802/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002803{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002804 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002805
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002806 if (!PyCallable_Check(func)) {
2807 PyErr_SetString(PyExc_TypeError, "bad argument list");
2808 return NULL;
2809 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002810
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002811 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002812
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002813 v = Tktt_New(func);
2814 if (v) {
2815 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2816 (ClientData)v);
2817 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002818
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002819 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002820}
2821
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002822
Guido van Rossum18468821994-06-20 07:49:28 +00002823/** Event Loop **/
2824
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002825/*[clinic input]
2826_tkinter.tkapp.mainloop
2827
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002828 threshold: int = 0
2829 /
2830
2831[clinic start generated code]*/
2832
Guido van Rossum18468821994-06-20 07:49:28 +00002833static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002834_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002835/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002836{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002837 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002838
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002839 CHECK_TCL_APPARTMENT;
2840 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002841
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002842 quitMainLoop = 0;
2843 while (Tk_GetNumMainWindows() > threshold &&
2844 !quitMainLoop &&
2845 !errorInCmd)
2846 {
2847 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002848
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002849 if (self->threaded) {
2850 /* Allow other Python threads to run. */
2851 ENTER_TCL
2852 result = Tcl_DoOneEvent(0);
2853 LEAVE_TCL
2854 }
2855 else {
2856 Py_BEGIN_ALLOW_THREADS
2857 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2858 tcl_tstate = tstate;
2859 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2860 tcl_tstate = NULL;
2861 if(tcl_lock)PyThread_release_lock(tcl_lock);
2862 if (result == 0)
2863 Sleep(Tkinter_busywaitinterval);
2864 Py_END_ALLOW_THREADS
2865 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002866
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002867 if (PyErr_CheckSignals() != 0) {
2868 self->dispatching = 0;
2869 return NULL;
2870 }
2871 if (result < 0)
2872 break;
2873 }
2874 self->dispatching = 0;
2875 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002876
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002877 if (errorInCmd) {
2878 errorInCmd = 0;
2879 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2880 excInCmd = valInCmd = trbInCmd = NULL;
2881 return NULL;
2882 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002883 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002884}
2885
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002886/*[clinic input]
2887_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002888
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002889 flags: int = 0
2890 /
2891
2892[clinic start generated code]*/
2893
2894static PyObject *
2895_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2896/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2897{
2898 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002899
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002900 ENTER_TCL
2901 rv = Tcl_DoOneEvent(flags);
2902 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002903 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002904}
2905
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002906/*[clinic input]
2907_tkinter.tkapp.quit
2908[clinic start generated code]*/
2909
Guido van Rossum062cfb01995-01-10 17:42:51 +00002910static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002911_tkinter_tkapp_quit_impl(TkappObject *self)
2912/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002913{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002914 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002915 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002916}
2917
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002918/*[clinic input]
2919_tkinter.tkapp.interpaddr
2920[clinic start generated code]*/
2921
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002922static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002923_tkinter_tkapp_interpaddr_impl(TkappObject *self)
2924/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002925{
Victor Stinnere1040e22013-09-05 00:22:24 +02002926 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002927}
2928
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002929/*[clinic input]
2930_tkinter.tkapp.loadtk
2931[clinic start generated code]*/
2932
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002933static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002934_tkinter_tkapp_loadtk_impl(TkappObject *self)
2935/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00002936{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002937 Tcl_Interp *interp = Tkapp_Interp(self);
2938 const char * _tk_exists = NULL;
2939 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002940
Guilherme Polob681df42009-02-09 22:33:59 +00002941#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002942 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2943 * first call failed.
2944 * To avoid the deadlock, we just refuse the second call through
2945 * a static variable.
2946 */
2947 if (tk_load_failed) {
2948 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2949 return NULL;
2950 }
Guilherme Polob681df42009-02-09 22:33:59 +00002951#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002952
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002953 /* We want to guard against calling Tk_Init() multiple times */
2954 CHECK_TCL_APPARTMENT;
2955 ENTER_TCL
2956 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2957 ENTER_OVERLAP
2958 if (err == TCL_ERROR) {
2959 /* This sets an exception, but we cannot return right
2960 away because we need to exit the overlap first. */
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002961 Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002962 } else {
2963 _tk_exists = Tkapp_Result(self);
2964 }
2965 LEAVE_OVERLAP_TCL
2966 if (err == TCL_ERROR) {
2967 return NULL;
2968 }
2969 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2970 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002971 PyErr_SetString(Tkinter_TclError,
2972 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002973#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002974 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002975#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002976 return NULL;
2977 }
2978 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002979 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002980}
Barry Warsawfa701a81997-01-16 00:15:11 +00002981
Martin v. Löwisffad6332002-11-26 09:28:05 +00002982static PyObject *
2983Tkapp_WantObjects(PyObject *self, PyObject *args)
2984{
2985
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002986 int wantobjects = -1;
2987 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2988 return NULL;
2989 if (wantobjects == -1)
2990 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2991 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002992
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002993 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002994}
2995
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002996/*[clinic input]
2997_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002998
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002999[clinic start generated code]*/
3000
3001static PyObject *
3002_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03003003/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003004{
3005 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003006
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003007 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003008}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003010
Guido van Rossum18468821994-06-20 07:49:28 +00003011/**** Tkapp Type Methods ****/
3012
3013static void
Fred Drake509d79a2000-07-08 04:04:38 +00003014Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003015{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003016 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003017 /*CHECK_TCL_APPARTMENT;*/
3018 ENTER_TCL
3019 Tcl_DeleteInterp(Tkapp_Interp(self));
3020 LEAVE_TCL
3021 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003022 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003023 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003024}
3025
Barry Warsawfa701a81997-01-16 00:15:11 +00003026
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003027
Guido van Rossum18468821994-06-20 07:49:28 +00003028/**** Tkinter Module ****/
3029
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003030typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003031 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003032 Py_ssize_t size; /* current size */
3033 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003034} FlattenContext;
3035
3036static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003037_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003038{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003039 /* expand tuple to hold (at least) size new items.
3040 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003041
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003042 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003043
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003044 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003045 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003046
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003047 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003048
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003049 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003050}
3051
3052static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003053_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003054{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003055 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003056
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003057 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003058
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003059 if (depth > 1000) {
3060 PyErr_SetString(PyExc_ValueError,
3061 "nesting too deep in _flatten");
3062 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003063 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3064 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003065 /* preallocate (assume no nesting) */
3066 if (context->size + size > context->maxsize &&
3067 !_bump(context, size))
3068 return 0;
3069 /* copy items to output tuple */
3070 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003071 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003072 if (PyList_Check(o) || PyTuple_Check(o)) {
3073 if (!_flatten1(context, o, depth + 1))
3074 return 0;
3075 } else if (o != Py_None) {
3076 if (context->size + 1 > context->maxsize &&
3077 !_bump(context, 1))
3078 return 0;
3079 Py_INCREF(o);
3080 PyTuple_SET_ITEM(context->tuple,
3081 context->size++, o);
3082 }
3083 }
3084 } else {
3085 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3086 return 0;
3087 }
3088 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003089}
3090
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003091/*[clinic input]
3092_tkinter._flatten
3093
3094 item: object
3095 /
3096
3097[clinic start generated code]*/
3098
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003099static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003100_tkinter__flatten(PyObject *module, PyObject *item)
3101/*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003102{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003103 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003105 context.maxsize = PySequence_Size(item);
3106 if (context.maxsize < 0)
3107 return NULL;
3108 if (context.maxsize == 0)
3109 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003110
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003111 context.tuple = PyTuple_New(context.maxsize);
3112 if (!context.tuple)
3113 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003114
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003115 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003116
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003117 if (!_flatten1(&context, item,0))
3118 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003119
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003120 if (_PyTuple_Resize(&context.tuple, context.size))
3121 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003122
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003123 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003124}
3125
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003126/*[clinic input]
3127_tkinter.create
3128
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003129 screenName: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003130 baseName: str = NULL
3131 className: str = "Tk"
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003132 interactive: bool(accept={int}) = False
3133 wantobjects: bool(accept={int}) = False
3134 wantTk: bool(accept={int}) = True
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003135 if false, then Tk_Init() doesn't get called
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003136 sync: bool(accept={int}) = False
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003137 if true, then pass -sync to wish
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003138 use: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003139 if not None, then pass -use to wish
3140 /
3141
3142[clinic start generated code]*/
3143
Guido van Rossum18468821994-06-20 07:49:28 +00003144static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003145_tkinter_create_impl(PyObject *module, const char *screenName,
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003146 const char *baseName, const char *className,
3147 int interactive, int wantobjects, int wantTk, int sync,
3148 const char *use)
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003149/*[clinic end generated code: output=e3315607648e6bb4 input=431907c134c80085]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003150{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003151 /* XXX baseName is not used anymore;
3152 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003153 CHECK_STRING_LENGTH(screenName);
3154 CHECK_STRING_LENGTH(baseName);
3155 CHECK_STRING_LENGTH(className);
3156 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003157
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003158 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003159 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003160 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003161}
3162
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003163/*[clinic input]
3164_tkinter.setbusywaitinterval
3165
3166 new_val: int
3167 /
3168
3169Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3170
3171It should be set to a divisor of the maximum time between frames in an animation.
3172[clinic start generated code]*/
3173
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003174static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003175_tkinter_setbusywaitinterval_impl(PyObject *module, int new_val)
3176/*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003177{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003178 if (new_val < 0) {
3179 PyErr_SetString(PyExc_ValueError,
3180 "busywaitinterval must be >= 0");
3181 return NULL;
3182 }
3183 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003184 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003185}
3186
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003187/*[clinic input]
3188_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003189
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003190Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3191[clinic start generated code]*/
3192
3193static int
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003194_tkinter_getbusywaitinterval_impl(PyObject *module)
3195/*[clinic end generated code: output=23b72d552001f5c7 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003196{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003197 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003198}
3199
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003200#include "clinic/_tkinter.c.h"
3201
3202static PyMethodDef Tktt_methods[] =
3203{
3204 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3205 {NULL, NULL}
3206};
3207
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003208static PyType_Slot Tktt_Type_slots[] = {
3209 {Py_tp_dealloc, Tktt_Dealloc},
3210 {Py_tp_repr, Tktt_Repr},
3211 {Py_tp_methods, Tktt_methods},
3212 {0, 0}
3213};
3214
3215static PyType_Spec Tktt_Type_spec = {
3216 "_tkinter.tktimertoken",
3217 sizeof(TkttObject),
3218 0,
3219 Py_TPFLAGS_DEFAULT,
3220 Tktt_Type_slots,
3221};
3222
3223
3224/**** Tkapp Method List ****/
3225
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003226static PyMethodDef Tkapp_methods[] =
3227{
3228 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3229 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3230 {"call", Tkapp_Call, METH_VARARGS},
3231 _TKINTER_TKAPP_EVAL_METHODDEF
3232 _TKINTER_TKAPP_EVALFILE_METHODDEF
3233 _TKINTER_TKAPP_RECORD_METHODDEF
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03003234 _TKINTER_TKAPP_ADDERRORINFO_METHODDEF
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003235 {"setvar", Tkapp_SetVar, METH_VARARGS},
3236 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3237 {"getvar", Tkapp_GetVar, METH_VARARGS},
3238 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3239 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3240 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3241 _TKINTER_TKAPP_GETINT_METHODDEF
3242 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3243 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3244 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3245 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3246 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3247 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3248 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3249 _TKINTER_TKAPP_SPLIT_METHODDEF
3250 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3251 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3252 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3253 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3254 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3255 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3256 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3257 _TKINTER_TKAPP_QUIT_METHODDEF
3258 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3259 _TKINTER_TKAPP_LOADTK_METHODDEF
3260 {NULL, NULL}
3261};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003262
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003263static PyType_Slot Tkapp_Type_slots[] = {
3264 {Py_tp_dealloc, Tkapp_Dealloc},
3265 {Py_tp_methods, Tkapp_methods},
3266 {0, 0}
3267};
3268
3269
3270static PyType_Spec Tkapp_Type_spec = {
3271 "_tkinter.tkapp",
3272 sizeof(TkappObject),
3273 0,
3274 Py_TPFLAGS_DEFAULT,
3275 Tkapp_Type_slots,
3276};
3277
Guido van Rossum18468821994-06-20 07:49:28 +00003278static PyMethodDef moduleMethods[] =
3279{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003280 _TKINTER__FLATTEN_METHODDEF
3281 _TKINTER_CREATE_METHODDEF
3282 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3283 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003284 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003285};
3286
Guido van Rossum7bf15641998-05-22 18:28:17 +00003287#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003288
3289static int stdin_ready = 0;
3290
Guido van Rossumad4db171998-06-13 13:56:28 +00003291#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003292static void
Fred Drake509d79a2000-07-08 04:04:38 +00003293MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003294{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003295 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003296}
Guido van Rossumad4db171998-06-13 13:56:28 +00003297#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003298
Guido van Rossum00d93061998-05-28 23:06:38 +00003299static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003300
Guido van Rossum18468821994-06-20 07:49:28 +00003301static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003302EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003303{
Guido van Rossumad4db171998-06-13 13:56:28 +00003304#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003305 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003306#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003307 PyEval_RestoreThread(event_tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003308 stdin_ready = 0;
3309 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003310#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003311 tfile = fileno(stdin);
3312 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003313#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003314 while (!errorInCmd && !stdin_ready) {
3315 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003316#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003317 if (_kbhit()) {
3318 stdin_ready = 1;
3319 break;
3320 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003321#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003322 Py_BEGIN_ALLOW_THREADS
3323 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3324 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003326 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003327
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003328 tcl_tstate = NULL;
3329 if(tcl_lock)PyThread_release_lock(tcl_lock);
3330 if (result == 0)
3331 Sleep(Tkinter_busywaitinterval);
3332 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003333
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003334 if (result < 0)
3335 break;
3336 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003337#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003338 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003339#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003340 if (errorInCmd) {
3341 errorInCmd = 0;
3342 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3343 excInCmd = valInCmd = trbInCmd = NULL;
3344 PyErr_Print();
3345 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003346 PyEval_SaveThread();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003347 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003348}
Guido van Rossum18468821994-06-20 07:49:28 +00003349
Guido van Rossum00d93061998-05-28 23:06:38 +00003350#endif
3351
Guido van Rossum7bf15641998-05-22 18:28:17 +00003352static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003353EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003354{
Guido van Rossum00d93061998-05-28 23:06:38 +00003355#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003356 if (PyOS_InputHook == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003357 event_tstate = PyThreadState_Get();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003358 PyOS_InputHook = EventHook;
3359 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003360#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003361}
3362
3363static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003364DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003365{
Guido van Rossum00d93061998-05-28 23:06:38 +00003366#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003367 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3368 PyOS_InputHook = NULL;
3369 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003370#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003371}
3372
Barry Warsawfa701a81997-01-16 00:15:11 +00003373
Martin v. Löwis1a214512008-06-11 05:26:20 +00003374static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003375 PyModuleDef_HEAD_INIT,
3376 "_tkinter",
3377 NULL,
3378 -1,
3379 moduleMethods,
3380 NULL,
3381 NULL,
3382 NULL,
3383 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003384};
3385
Mark Hammond62b1ab12002-07-23 06:31:15 +00003386PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003387PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003388{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003389 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003391 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003392 if (tcl_lock == NULL)
3393 return NULL;
Guido van Rossumae92f011996-08-21 19:03:36 +00003394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003395 m = PyModule_Create(&_tkintermodule);
3396 if (m == NULL)
3397 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003398
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003399 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3400 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003401 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003402 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003403 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003404 Py_INCREF(o);
3405 if (PyModule_AddObject(m, "TclError", o)) {
3406 Py_DECREF(o);
3407 Py_DECREF(m);
3408 return NULL;
3409 }
3410 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003411
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003412 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3413 Py_DECREF(m);
3414 return NULL;
3415 }
3416 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3417 Py_DECREF(m);
3418 return NULL;
3419 }
3420 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3421 Py_DECREF(m);
3422 return NULL;
3423 }
3424 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3425 Py_DECREF(m);
3426 return NULL;
3427 }
3428 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3429 Py_DECREF(m);
3430 return NULL;
3431 }
3432 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3433 Py_DECREF(m);
3434 return NULL;
3435 }
3436 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3437 Py_DECREF(m);
3438 return NULL;
3439 }
3440 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3441 Py_DECREF(m);
3442 return NULL;
3443 }
3444 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3445 Py_DECREF(m);
3446 return NULL;
3447 }
3448 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3449 Py_DECREF(m);
3450 return NULL;
3451 }
3452 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3453 Py_DECREF(m);
3454 return NULL;
3455 }
3456
3457 o = PyType_FromSpec(&Tkapp_Type_spec);
3458 if (o == NULL) {
3459 Py_DECREF(m);
3460 return NULL;
3461 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003462 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003463 if (PyModule_AddObject(m, "TkappType", o)) {
3464 Py_DECREF(o);
3465 Py_DECREF(m);
3466 return NULL;
3467 }
3468 Tkapp_Type = o;
3469
3470 o = PyType_FromSpec(&Tktt_Type_spec);
3471 if (o == NULL) {
3472 Py_DECREF(m);
3473 return NULL;
3474 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003475 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003476 if (PyModule_AddObject(m, "TkttType", o)) {
3477 Py_DECREF(o);
3478 Py_DECREF(m);
3479 return NULL;
3480 }
3481 Tktt_Type = o;
3482
3483 o = PyType_FromSpec(&PyTclObject_Type_spec);
3484 if (o == NULL) {
3485 Py_DECREF(m);
3486 return NULL;
3487 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003488 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003489 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3490 Py_DECREF(o);
3491 Py_DECREF(m);
3492 return NULL;
3493 }
3494 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003495
3496#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003497 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3498 * start waking up. Note that Tcl_FindExecutable will do this, this
3499 * code must be above it! The original warning from
3500 * tkMacOSXAppInit.c is copied below.
3501 *
3502 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3503 * Tcl interpreter for now. It probably should work to do this
3504 * in the other order, but for now it doesn't seem to.
3505 *
3506 */
3507 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003508#endif
3509
3510
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003511 /* This helps the dynamic loader; in Unicode aware Tcl versions
3512 it also helps Tcl find its encodings. */
3513 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3514 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003515 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003516 if (cexe) {
3517#ifdef MS_WINDOWS
3518 int set_var = 0;
3519 PyObject *str_path;
3520 wchar_t *wcs_path;
3521 DWORD ret;
3522
3523 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3524
3525 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3526 str_path = _get_tcl_lib_path();
3527 if (str_path == NULL && PyErr_Occurred()) {
3528 return NULL;
3529 }
3530 if (str_path != NULL) {
3531 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3532 if (wcs_path == NULL) {
3533 return NULL;
3534 }
3535 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3536 set_var = 1;
3537 }
3538 }
3539
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003540 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003541
3542 if (set_var) {
3543 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3544 PyMem_Free(wcs_path);
3545 }
3546#else
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003547 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003548#endif /* MS_WINDOWS */
3549 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003550 Py_XDECREF(cexe);
3551 Py_DECREF(uexe);
3552 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003553
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003554 if (PyErr_Occurred()) {
3555 Py_DECREF(m);
3556 return NULL;
3557 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003558
Guido van Rossum43ff8681998-07-14 18:02:13 +00003559#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003560 /* This was not a good idea; through <Destroy> bindings,
3561 Tcl_Finalize() may invoke Python code but at that point the
3562 interpreter and thread state have already been destroyed! */
3563 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003564#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003565 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003566}