blob: 613a95b0897255154a539912e56f72515417ce03 [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;
Barry Warsawfa701a81997-01-16 00:15:11 +0000620
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000621 v->interp = Tcl_CreateInterp();
622 v->wantobjects = wantobjects;
623 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
624 TCL_GLOBAL_ONLY) != NULL;
625 v->thread_id = Tcl_GetCurrentThread();
626 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000627
628#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000629 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300630 PyErr_SetString(PyExc_RuntimeError,
631 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 Py_DECREF(v);
633 return 0;
634 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000635#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 if (v->threaded && tcl_lock) {
637 /* If Tcl is threaded, we don't need the lock. */
638 PyThread_free_lock(tcl_lock);
639 tcl_lock = NULL;
640 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000641
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200642 v->OldBooleanType = Tcl_GetObjType("boolean");
643 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000644 v->ByteArrayType = Tcl_GetObjType("bytearray");
645 v->DoubleType = Tcl_GetObjType("double");
646 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300647 v->WideIntType = Tcl_GetObjType("wideInt");
648 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000649 v->ListType = Tcl_GetObjType("list");
650 v->ProcBodyType = Tcl_GetObjType("procbody");
651 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000652
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 /* Delete the 'exit' command, which can screw things up */
654 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000655
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000656 if (screenName != NULL)
657 Tcl_SetVar2(v->interp, "env", "DISPLAY",
658 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000659
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 if (interactive)
661 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
662 else
663 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000664
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000665 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200666 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000667 if (!argv0) {
668 PyErr_NoMemory();
669 Py_DECREF(v);
670 return NULL;
671 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000673 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200674 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
675 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200677 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000678
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000679 if (! wantTk) {
680 Tcl_SetVar(v->interp,
681 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
682 }
Guilherme Polob681df42009-02-09 22:33:59 +0000683#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 else if (tk_load_failed) {
685 Tcl_SetVar(v->interp,
686 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
687 }
Guilherme Polob681df42009-02-09 22:33:59 +0000688#endif
David Aschere2b4b322004-02-18 05:59:53 +0000689
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 /* some initial arguments need to be in argv */
691 if (sync || use) {
692 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200693 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000695 if (sync)
696 len += sizeof "-sync";
697 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200698 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000699
Victor Stinneree6c3c72014-09-11 17:50:21 +0200700 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 if (!args) {
702 PyErr_NoMemory();
703 Py_DECREF(v);
704 return NULL;
705 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000706
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000707 args[0] = '\0';
708 if (sync)
709 strcat(args, "-sync");
710 if (use) {
711 if (sync)
712 strcat(args, " ");
713 strcat(args, "-use ");
714 strcat(args, use);
715 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200718 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000719 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000720
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500721#ifdef MS_WINDOWS
722 {
723 PyObject *str_path;
724 PyObject *utf8_path;
725 DWORD ret;
726
727 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
728 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
729 str_path = _get_tcl_lib_path();
730 if (str_path == NULL && PyErr_Occurred()) {
731 return NULL;
732 }
733 if (str_path != NULL) {
734 utf8_path = PyUnicode_AsUTF8String(str_path);
735 if (utf8_path == NULL) {
736 return NULL;
737 }
738 Tcl_SetVar(v->interp,
739 "tcl_library",
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300740 PyBytes_AS_STRING(utf8_path),
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500741 TCL_GLOBAL_ONLY);
742 Py_DECREF(utf8_path);
743 }
744 }
745 }
746#endif
747
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000748 if (Tcl_AppInit(v->interp) != TCL_OK) {
749 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000750#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000751 if (wantTk) {
752 const char *_tkinter_tk_failed;
753 _tkinter_tk_failed = Tcl_GetVar(v->interp,
754 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000755
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000756 if ( _tkinter_tk_failed != NULL &&
757 strcmp(_tkinter_tk_failed, "1") == 0) {
758 tk_load_failed = 1;
759 }
760 }
Guilherme Polob681df42009-02-09 22:33:59 +0000761#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000762 Py_DECREF((PyObject *)v);
763 return (TkappObject *)result;
764 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000765
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000766 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000767
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000768 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000769}
770
Barry Warsawfa701a81997-01-16 00:15:11 +0000771
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000772static void
773Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000774 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000775{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000776 Py_BEGIN_ALLOW_THREADS;
777 Tcl_MutexLock(mutex);
778 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
779 Tcl_ThreadAlert(self->thread_id);
780 Tcl_ConditionWait(cond, mutex, NULL);
781 Tcl_MutexUnlock(mutex);
782 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000783}
784
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000785
Guido van Rossum18468821994-06-20 07:49:28 +0000786/** Tcl Eval **/
787
Martin v. Löwisffad6332002-11-26 09:28:05 +0000788typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000789 PyObject_HEAD
790 Tcl_Obj *value;
791 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000792} PyTclObject;
793
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300794static PyObject *PyTclObject_Type;
795#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000796
797static PyObject *
798newPyTclObject(Tcl_Obj *arg)
799{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000800 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300801 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000802 if (self == NULL)
803 return NULL;
804 Tcl_IncrRefCount(arg);
805 self->value = arg;
806 self->string = NULL;
807 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000808}
809
810static void
811PyTclObject_dealloc(PyTclObject *self)
812{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200813 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000814 Tcl_DecrRefCount(self->value);
815 Py_XDECREF(self->string);
816 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200817 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000818}
819
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200820static const char *
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000821PyTclObject_TclString(PyObject *self)
822{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000823 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000824}
825
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000826/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000827PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000828"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000829
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000830static PyObject *
831PyTclObject_string(PyTclObject *self, void *ignored)
832{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000833 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200834 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000835 if (!self->string)
836 return NULL;
837 }
838 Py_INCREF(self->string);
839 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000840}
841
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000842static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200843PyTclObject_str(PyTclObject *self)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000844{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200845 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000846 Py_INCREF(self->string);
847 return self->string;
848 }
849 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200850 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000851}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000852
Martin v. Löwisffad6332002-11-26 09:28:05 +0000853static PyObject *
854PyTclObject_repr(PyTclObject *self)
855{
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200856 PyObject *repr, *str = PyTclObject_str(self);
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300857 if (str == NULL)
858 return NULL;
859 repr = PyUnicode_FromFormat("<%s object: %R>",
860 self->value->typePtr->name, str);
861 Py_DECREF(str);
862 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000863}
864
Mark Dickinson211c6252009-02-01 10:28:51 +0000865static PyObject *
866PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000867{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000868 int result;
Mark Dickinson211c6252009-02-01 10:28:51 +0000869
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000870 /* neither argument should be NULL, unless something's gone wrong */
871 if (self == NULL || other == NULL) {
872 PyErr_BadInternalCall();
873 return NULL;
874 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000876 /* both arguments should be instances of PyTclObject */
877 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
stratakise8b19652017-11-02 11:32:54 +0100878 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000879 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000880
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 if (self == other)
882 /* fast path when self and other are identical */
883 result = 0;
884 else
885 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
886 Tcl_GetString(((PyTclObject *)other)->value));
stratakise8b19652017-11-02 11:32:54 +0100887 Py_RETURN_RICHCOMPARE(result, 0, op);
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000888}
889
Martin v. Löwis39195712003-01-04 00:33:13 +0000890PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
891
Martin v. Löwisffad6332002-11-26 09:28:05 +0000892static PyObject*
893get_typename(PyTclObject* obj, void* ignored)
894{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200895 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000896}
897
Martin v. Löwis39195712003-01-04 00:33:13 +0000898
Martin v. Löwisffad6332002-11-26 09:28:05 +0000899static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000900 {"typename", (getter)get_typename, NULL, get_typename__doc__},
901 {"string", (getter)PyTclObject_string, NULL,
902 PyTclObject_string__doc__},
903 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000904};
905
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300906static PyType_Slot PyTclObject_Type_slots[] = {
907 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
908 {Py_tp_repr, (reprfunc)PyTclObject_repr},
909 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200910 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300911 {Py_tp_richcompare, PyTclObject_richcompare},
912 {Py_tp_getset, PyTclObject_getsetlist},
913 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000914};
915
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300916static PyType_Spec PyTclObject_Type_spec = {
917 "_tkinter.Tcl_Obj",
918 sizeof(PyTclObject),
919 0,
920 Py_TPFLAGS_DEFAULT,
921 PyTclObject_Type_slots,
922};
923
924
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700925#if SIZE_MAX > INT_MAX
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300926#define CHECK_STRING_LENGTH(s) do { \
927 if (s != NULL && strlen(s) >= INT_MAX) { \
928 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
929 return NULL; \
930 } } while(0)
931#else
932#define CHECK_STRING_LENGTH(s)
933#endif
934
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300935#ifdef HAVE_LIBTOMMAMTH
936static Tcl_Obj*
937asBignumObj(PyObject *value)
938{
939 Tcl_Obj *result;
940 int neg;
941 PyObject *hexstr;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200942 const char *hexchars;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300943 mp_int bigValue;
944
945 neg = Py_SIZE(value) < 0;
946 hexstr = _PyLong_Format(value, 16);
947 if (hexstr == NULL)
948 return NULL;
949 hexchars = PyUnicode_AsUTF8(hexstr);
950 if (hexchars == NULL) {
951 Py_DECREF(hexstr);
952 return NULL;
953 }
954 hexchars += neg + 2; /* skip sign and "0x" */
955 mp_init(&bigValue);
956 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
957 mp_clear(&bigValue);
958 Py_DECREF(hexstr);
959 PyErr_NoMemory();
960 return NULL;
961 }
962 Py_DECREF(hexstr);
963 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
964 result = Tcl_NewBignumObj(&bigValue);
965 mp_clear(&bigValue);
966 if (result == NULL) {
967 PyErr_NoMemory();
968 return NULL;
969 }
970 return result;
971}
972#endif
973
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000974static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000975AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000976{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000977 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000978
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200979 if (PyBytes_Check(value)) {
980 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
981 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
982 return NULL;
983 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300984 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200985 (int)PyBytes_GET_SIZE(value));
986 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300987
988 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000989 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300990
991 if (PyLong_CheckExact(value)) {
992 int overflow;
993 long longValue;
994#ifdef TCL_WIDE_INT_TYPE
995 Tcl_WideInt wideValue;
996#endif
997 longValue = PyLong_AsLongAndOverflow(value, &overflow);
998 if (!overflow) {
999 return Tcl_NewLongObj(longValue);
1000 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001001 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001002 fall through to wideInt handling. */
1003#ifdef TCL_WIDE_INT_TYPE
1004 if (_PyLong_AsByteArray((PyLongObject *)value,
1005 (unsigned char *)(void *)&wideValue,
1006 sizeof(wideValue),
1007 PY_LITTLE_ENDIAN,
1008 /* signed */ 1) == 0) {
1009 return Tcl_NewWideIntObj(wideValue);
1010 }
1011 PyErr_Clear();
1012#endif
1013 /* If there is an overflow in the wideInt conversion,
1014 fall through to bignum handling. */
1015#ifdef HAVE_LIBTOMMAMTH
1016 return asBignumObj(value);
1017#endif
1018 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001019 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001020 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001021
1022 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001023 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001024
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +03001025 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001026 Tcl_Obj **argv;
1027 Py_ssize_t size, i;
1028
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001029 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001030 if (size == 0)
1031 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001032 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001033 PyErr_SetString(PyExc_OverflowError,
1034 PyTuple_Check(value) ? "tuple is too long" :
1035 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001036 return NULL;
1037 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001038 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
1039 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001040 PyErr_NoMemory();
1041 return NULL;
1042 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001043 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001044 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001045 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001046 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001047 return result;
1048 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001049
1050 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001051 void *inbuf;
1052 Py_ssize_t size;
1053 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001054 Tcl_UniChar *outbuf = NULL;
1055 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001056 size_t allocsize;
1057
1058 if (PyUnicode_READY(value) == -1)
1059 return NULL;
1060
1061 inbuf = PyUnicode_DATA(value);
1062 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001063 if (size == 0)
1064 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001065 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1066 PyErr_SetString(PyExc_OverflowError, "string is too long");
1067 return NULL;
1068 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001069 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001070 if (kind == sizeof(Tcl_UniChar))
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001071 return Tcl_NewUnicodeObj(inbuf, (int)size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001072 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001073 outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001074 /* Else overflow occurred, and we take the next exit */
1075 if (!outbuf) {
1076 PyErr_NoMemory();
1077 return NULL;
1078 }
1079 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001080 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1081 /* We cannot test for sizeof(Tcl_UniChar) directly,
1082 so we test for UTF-8 size instead. */
1083#if TCL_UTF_MAX == 3
1084 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001085 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001086 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001087 "character U+%x is above the range "
1088 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001089 ch);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001090 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001091 return NULL;
1092 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001093#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001094 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001095 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001096 result = Tcl_NewUnicodeObj(outbuf, (int)size);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001097 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001098 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001099 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001100
1101 if (PyTclObject_Check(value)) {
Serhiy Storchakadf13df42018-10-23 22:40:54 +03001102 return ((PyTclObject*)value)->value;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001103 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001104
1105 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001106 PyObject *v = PyObject_Str(value);
1107 if (!v)
1108 return 0;
1109 result = AsObj(v);
1110 Py_DECREF(v);
1111 return result;
1112 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001113}
1114
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001115static PyObject *
1116fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1117{
1118 int boolValue;
1119 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1120 return Tkinter_Error(tkapp);
1121 return PyBool_FromLong(boolValue);
1122}
1123
Martin v. Löwisffad6332002-11-26 09:28:05 +00001124static PyObject*
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001125fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1126{
1127 Tcl_WideInt wideValue;
1128 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001129 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1130 return PyLong_FromLongLong(wideValue);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001131 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1132 sizeof(wideValue),
1133 PY_LITTLE_ENDIAN,
1134 /* signed */ 1);
1135 }
1136 return NULL;
1137}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001138
1139#ifdef HAVE_LIBTOMMAMTH
1140static PyObject*
1141fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1142{
1143 mp_int bigValue;
1144 unsigned long numBytes;
1145 unsigned char *bytes;
1146 PyObject *res;
1147
1148 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1149 return Tkinter_Error(tkapp);
1150 numBytes = mp_unsigned_bin_size(&bigValue);
1151 bytes = PyMem_Malloc(numBytes);
1152 if (bytes == NULL) {
1153 mp_clear(&bigValue);
1154 return PyErr_NoMemory();
1155 }
1156 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1157 &numBytes) != MP_OKAY) {
1158 mp_clear(&bigValue);
1159 PyMem_Free(bytes);
1160 return PyErr_NoMemory();
1161 }
1162 res = _PyLong_FromByteArray(bytes, numBytes,
1163 /* big-endian */ 0,
1164 /* unsigned */ 0);
1165 PyMem_Free(bytes);
1166 if (res != NULL && bigValue.sign == MP_NEG) {
1167 PyObject *res2 = PyNumber_Negative(res);
1168 Py_DECREF(res);
1169 res = res2;
1170 }
1171 mp_clear(&bigValue);
1172 return res;
1173}
1174#endif
1175
Martin v. Löwisffad6332002-11-26 09:28:05 +00001176static PyObject*
1177FromObj(PyObject* tkapp, Tcl_Obj *value)
1178{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001179 PyObject *result = NULL;
1180 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001181 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001182
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001183 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001184 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001185 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001186
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001187 if (value->typePtr == app->BooleanType ||
1188 value->typePtr == app->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001189 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001190 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001191
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001192 if (value->typePtr == app->ByteArrayType) {
1193 int size;
1194 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1195 return PyBytes_FromStringAndSize(data, size);
1196 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001198 if (value->typePtr == app->DoubleType) {
1199 return PyFloat_FromDouble(value->internalRep.doubleValue);
1200 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001201
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001202 if (value->typePtr == app->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001203 long longValue;
1204 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1205 return PyLong_FromLong(longValue);
1206 /* If there is an error in the long conversion,
1207 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001208 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001209
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001210 if (value->typePtr == app->IntType ||
1211 value->typePtr == app->WideIntType) {
1212 result = fromWideIntObj(tkapp, value);
1213 if (result != NULL || PyErr_Occurred())
1214 return result;
1215 Tcl_ResetResult(interp);
1216 /* If there is an error in the wideInt conversion,
1217 fall through to bignum handling. */
1218 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001219
1220#ifdef HAVE_LIBTOMMAMTH
1221 if (value->typePtr == app->IntType ||
1222 value->typePtr == app->WideIntType ||
1223 value->typePtr == app->BignumType) {
1224 return fromBignumObj(tkapp, value);
1225 }
1226#endif
1227
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001228 if (value->typePtr == app->ListType) {
1229 int size;
1230 int i, status;
1231 PyObject *elem;
1232 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001233
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001234 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001235 if (status == TCL_ERROR)
1236 return Tkinter_Error(tkapp);
1237 result = PyTuple_New(size);
1238 if (!result)
1239 return NULL;
1240 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001241 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001242 if (status == TCL_ERROR) {
1243 Py_DECREF(result);
1244 return Tkinter_Error(tkapp);
1245 }
1246 elem = FromObj(tkapp, tcl_elem);
1247 if (!elem) {
1248 Py_DECREF(result);
1249 return NULL;
1250 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001251 PyTuple_SET_ITEM(result, i, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001252 }
1253 return result;
1254 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001255
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001256 if (value->typePtr == app->ProcBodyType) {
1257 /* fall through: return tcl object. */
1258 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001260 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001261 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001262 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001263 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001264 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001265
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001266#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001267 if (app->BooleanType == NULL &&
1268 strcmp(value->typePtr->name, "booleanString") == 0) {
1269 /* booleanString type is not registered in Tcl */
1270 app->BooleanType = value->typePtr;
1271 return fromBoolean(tkapp, value);
1272 }
1273#endif
1274
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001275#ifdef HAVE_LIBTOMMAMTH
1276 if (app->BignumType == NULL &&
1277 strcmp(value->typePtr->name, "bignum") == 0) {
1278 /* bignum type is not registered in Tcl */
1279 app->BignumType = value->typePtr;
1280 return fromBignumObj(tkapp, value);
1281 }
1282#endif
1283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001285}
1286
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001287/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001288TCL_DECLARE_MUTEX(call_mutex)
1289
1290typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001291 Tcl_Event ev; /* Must be first */
1292 TkappObject *self;
1293 PyObject *args;
1294 int flags;
1295 PyObject **res;
1296 PyObject **exc_type, **exc_value, **exc_tb;
1297 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001298} Tkapp_CallEvent;
1299
1300void
1301Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001302{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001303 int i;
1304 for (i = 0; i < objc; i++)
1305 Tcl_DecrRefCount(objv[i]);
1306 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001307 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001308}
Guido van Rossum18468821994-06-20 07:49:28 +00001309
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001310/* Convert Python objects to Tcl objects. This must happen in the
1311 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001312
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001313static Tcl_Obj**
1314Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1315{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001316 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001317 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001318 if (args == NULL)
1319 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001320
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001321 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001322 objv[0] = AsObj(args);
Serhiy Storchaka0b3ec192017-03-23 17:53:47 +02001323 if (objv[0] == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001324 goto finally;
1325 objc = 1;
1326 Tcl_IncrRefCount(objv[0]);
1327 }
1328 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001329 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001330
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001331 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001332 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001333 PyErr_SetString(PyExc_OverflowError,
1334 PyTuple_Check(args) ? "tuple is too long" :
1335 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001336 return NULL;
1337 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001338 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001339 if (objv == NULL) {
1340 PyErr_NoMemory();
1341 objc = 0;
1342 goto finally;
1343 }
1344 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001345
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001347 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001348 if (v == Py_None) {
1349 objc = i;
1350 break;
1351 }
1352 objv[i] = AsObj(v);
1353 if (!objv[i]) {
1354 /* Reset objc, so it attempts to clear
1355 objects only up to i. */
1356 objc = i;
1357 goto finally;
1358 }
1359 Tcl_IncrRefCount(objv[i]);
1360 }
1361 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001362 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001363 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001364finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001365 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001366 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001367}
Guido van Rossum212643f1998-04-29 16:22:14 +00001368
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001369/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001370
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001371static PyObject*
1372Tkapp_CallResult(TkappObject *self)
1373{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001374 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001375 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001376 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001377 /* Not sure whether the IncrRef is necessary, but something
1378 may overwrite the interpreter result while we are
1379 converting it. */
1380 Tcl_IncrRefCount(value);
1381 res = FromObj((PyObject*)self, value);
1382 Tcl_DecrRefCount(value);
1383 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001384 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001385 }
1386 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001387}
Guido van Rossum632de272000-03-29 00:19:50 +00001388
Benjamin Peterson5879d412009-03-30 14:51:56 +00001389
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001390/* Tkapp_CallProc is the event procedure that is executed in the context of
1391 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1392 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001393
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001394static int
1395Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1396{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001397 Tcl_Obj *objStore[ARGSZ];
1398 Tcl_Obj **objv;
1399 int objc;
1400 int i;
1401 ENTER_PYTHON
1402 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1403 if (!objv) {
1404 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1405 *(e->res) = NULL;
1406 }
1407 LEAVE_PYTHON
1408 if (!objv)
1409 goto done;
1410 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1411 ENTER_PYTHON
1412 if (i == TCL_ERROR) {
1413 *(e->res) = NULL;
1414 *(e->exc_type) = NULL;
1415 *(e->exc_tb) = NULL;
1416 *(e->exc_value) = PyObject_CallFunction(
1417 Tkinter_TclError, "s",
1418 Tcl_GetStringResult(e->self->interp));
1419 }
1420 else {
1421 *(e->res) = Tkapp_CallResult(e->self);
1422 }
1423 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001424
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001425 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001426done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001427 /* Wake up calling thread. */
1428 Tcl_MutexLock(&call_mutex);
1429 Tcl_ConditionNotify(e->done);
1430 Tcl_MutexUnlock(&call_mutex);
1431 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001432}
1433
Benjamin Peterson5879d412009-03-30 14:51:56 +00001434
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001435/* This is the main entry point for calling a Tcl command.
1436 It supports three cases, with regard to threading:
1437 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1438 the context of the calling thread.
1439 2. Tcl is threaded, caller of the command is in the interpreter thread:
1440 Execute the command in the calling thread. Since the Tcl lock will
1441 not be used, we can merge that with case 1.
1442 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1443 the interpreter thread. Allocation of Tcl objects needs to occur in the
1444 interpreter thread, so we ship the PyObject* args to the target thread,
1445 and perform processing there. */
1446
1447static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001448Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001449{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001450 Tcl_Obj *objStore[ARGSZ];
1451 Tcl_Obj **objv = NULL;
1452 int objc, i;
1453 PyObject *res = NULL;
1454 TkappObject *self = (TkappObject*)selfptr;
1455 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001456
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001457 /* If args is a single tuple, replace with contents of tuple */
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001458 if (PyTuple_GET_SIZE(args) == 1) {
1459 PyObject *item = PyTuple_GET_ITEM(args, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001460 if (PyTuple_Check(item))
1461 args = item;
1462 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001463 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1464 /* We cannot call the command directly. Instead, we must
1465 marshal the parameters to the interpreter thread. */
1466 Tkapp_CallEvent *ev;
1467 Tcl_Condition cond = NULL;
1468 PyObject *exc_type, *exc_value, *exc_tb;
1469 if (!WaitForMainloop(self))
1470 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001471 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1472 if (ev == NULL) {
1473 PyErr_NoMemory();
1474 return NULL;
1475 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001476 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1477 ev->self = self;
1478 ev->args = args;
1479 ev->res = &res;
1480 ev->exc_type = &exc_type;
1481 ev->exc_value = &exc_value;
1482 ev->exc_tb = &exc_tb;
1483 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001484
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001485 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001487 if (res == NULL) {
1488 if (exc_type)
1489 PyErr_Restore(exc_type, exc_value, exc_tb);
1490 else
1491 PyErr_SetObject(Tkinter_TclError, exc_value);
1492 }
1493 Tcl_ConditionFinalize(&cond);
1494 }
1495 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001496 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001497
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001498 objv = Tkapp_CallArgs(args, objStore, &objc);
1499 if (!objv)
1500 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001501
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001502 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001503
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001504 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001506 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001508 if (i == TCL_ERROR)
1509 Tkinter_Error(selfptr);
1510 else
1511 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001512
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001513 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001514
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001515 Tkapp_CallDeallocArgs(objv, objStore, objc);
1516 }
1517 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001518}
1519
1520
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001521/*[clinic input]
1522_tkinter.tkapp.eval
1523
1524 script: str
1525 /
1526
1527[clinic start generated code]*/
1528
Barry Warsawfa701a81997-01-16 00:15:11 +00001529static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001530_tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1531/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001532{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 PyObject *res = NULL;
1534 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001535
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001536 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001537 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001539 ENTER_TCL
1540 err = Tcl_Eval(Tkapp_Interp(self), script);
1541 ENTER_OVERLAP
1542 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001543 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001544 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001545 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001546 LEAVE_OVERLAP_TCL
1547 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001548}
1549
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001550/*[clinic input]
1551_tkinter.tkapp.evalfile
1552
1553 fileName: str
1554 /
1555
1556[clinic start generated code]*/
1557
Guido van Rossum18468821994-06-20 07:49:28 +00001558static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001559_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1560/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001561{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001562 PyObject *res = NULL;
1563 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001564
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001565 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001567
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 ENTER_TCL
1569 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1570 ENTER_OVERLAP
1571 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001572 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001573 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001574 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001575 LEAVE_OVERLAP_TCL
1576 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001577}
1578
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001579/*[clinic input]
1580_tkinter.tkapp.record
1581
1582 script: str
1583 /
1584
1585[clinic start generated code]*/
1586
Guido van Rossum18468821994-06-20 07:49:28 +00001587static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001588_tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1589/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001590{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001591 PyObject *res = NULL;
1592 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001593
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001594 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001595 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001596
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001597 ENTER_TCL
1598 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1599 ENTER_OVERLAP
1600 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001601 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001602 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001603 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001604 LEAVE_OVERLAP_TCL
1605 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001606}
1607
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001608/*[clinic input]
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001609_tkinter.tkapp.adderrorinfo
Guido van Rossum18468821994-06-20 07:49:28 +00001610
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001611 msg: str
1612 /
1613
1614[clinic start generated code]*/
1615
1616static PyObject *
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001617_tkinter_tkapp_adderrorinfo_impl(TkappObject *self, const char *msg)
1618/*[clinic end generated code: output=52162eaca2ee53cb input=f4b37aec7c7e8c77]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001619{
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001620 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001621 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001622
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001623 ENTER_TCL
1624 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1625 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001626
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001627 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001628}
1629
Barry Warsawfa701a81997-01-16 00:15:11 +00001630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001631
Guido van Rossum18468821994-06-20 07:49:28 +00001632/** Tcl Variable **/
1633
Benjamin Peterson5879d412009-03-30 14:51:56 +00001634typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1635
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001636TCL_DECLARE_MUTEX(var_mutex)
1637
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001638typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001639 Tcl_Event ev; /* must be first */
1640 PyObject *self;
1641 PyObject *args;
1642 int flags;
1643 EventFunc func;
1644 PyObject **res;
1645 PyObject **exc_type;
1646 PyObject **exc_val;
1647 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001648} VarEvent;
1649
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001650/*[python]
1651
1652class varname_converter(CConverter):
1653 type = 'const char *'
1654 converter = 'varname_converter'
1655
1656[python]*/
1657/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1658
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001659static int
1660varname_converter(PyObject *in, void *_out)
1661{
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +02001662 const char *s;
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001663 const char **out = (const char**)_out;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001664 if (PyBytes_Check(in)) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001665 if (PyBytes_GET_SIZE(in) > INT_MAX) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001666 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1667 return 0;
1668 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001669 s = PyBytes_AS_STRING(in);
1670 if (strlen(s) != (size_t)PyBytes_GET_SIZE(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001671 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001672 return 0;
1673 }
1674 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001675 return 1;
1676 }
1677 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001678 Py_ssize_t size;
1679 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001680 if (s == NULL) {
1681 return 0;
1682 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001683 if (size > INT_MAX) {
1684 PyErr_SetString(PyExc_OverflowError, "string is too long");
1685 return 0;
1686 }
Victor Stinner706768c2014-08-16 01:03:39 +02001687 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001688 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001689 return 0;
1690 }
1691 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001692 return 1;
1693 }
1694 if (PyTclObject_Check(in)) {
1695 *out = PyTclObject_TclString(in);
1696 return 1;
1697 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001698 PyErr_Format(PyExc_TypeError,
1699 "must be str, bytes or Tcl_Obj, not %.50s",
1700 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001701 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001702}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001703
Benjamin Peterson5879d412009-03-30 14:51:56 +00001704
Martin v. Löwis59683e82008-06-13 07:50:45 +00001705static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001706var_perform(VarEvent *ev)
1707{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001708 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1709 if (!*(ev->res)) {
1710 PyObject *exc, *val, *tb;
1711 PyErr_Fetch(&exc, &val, &tb);
1712 PyErr_NormalizeException(&exc, &val, &tb);
1713 *(ev->exc_type) = exc;
1714 *(ev->exc_val) = val;
Serhiy Storchaka3ec5f422016-10-28 12:14:34 +03001715 Py_XDECREF(tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001716 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001717
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001718}
1719
1720static int
1721var_proc(VarEvent* ev, int flags)
1722{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001723 ENTER_PYTHON
1724 var_perform(ev);
1725 Tcl_MutexLock(&var_mutex);
1726 Tcl_ConditionNotify(ev->cond);
1727 Tcl_MutexUnlock(&var_mutex);
1728 LEAVE_PYTHON
1729 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001730}
1731
Benjamin Peterson5879d412009-03-30 14:51:56 +00001732
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001733static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001734var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001735{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001736 TkappObject *self = (TkappObject*)selfptr;
1737 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 VarEvent *ev;
1739 PyObject *res, *exc_type, *exc_val;
1740 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001741
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001742 /* The current thread is not the interpreter thread. Marshal
1743 the call to the interpreter thread, then wait for
1744 completion. */
1745 if (!WaitForMainloop(self))
1746 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001747
Serhiy Storchaka07940882014-09-11 10:38:54 +03001748 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1749 if (ev == NULL) {
1750 PyErr_NoMemory();
1751 return NULL;
1752 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001753 ev->self = selfptr;
1754 ev->args = args;
1755 ev->flags = flags;
1756 ev->func = func;
1757 ev->res = &res;
1758 ev->exc_type = &exc_type;
1759 ev->exc_val = &exc_val;
1760 ev->cond = &cond;
1761 ev->ev.proc = (Tcl_EventProc*)var_proc;
1762 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1763 Tcl_ConditionFinalize(&cond);
1764 if (!res) {
1765 PyErr_SetObject(exc_type, exc_val);
1766 Py_DECREF(exc_type);
1767 Py_DECREF(exc_val);
1768 return NULL;
1769 }
1770 return res;
1771 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001772 /* Tcl is not threaded, or this is the interpreter thread. */
1773 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001774}
1775
Guido van Rossum18468821994-06-20 07:49:28 +00001776static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001777SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001778{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001779 const char *name1, *name2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001780 PyObject *newValue;
1781 PyObject *res = NULL;
1782 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001783
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001784 switch (PyTuple_GET_SIZE(args)) {
1785 case 2:
1786 if (!PyArg_ParseTuple(args, "O&O:setvar",
1787 varname_converter, &name1, &newValue))
1788 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001789 /* XXX Acquire tcl lock??? */
1790 newval = AsObj(newValue);
1791 if (newval == NULL)
1792 return NULL;
1793 ENTER_TCL
1794 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1795 newval, flags);
1796 ENTER_OVERLAP
1797 if (!ok)
1798 Tkinter_Error(self);
1799 else {
1800 res = Py_None;
1801 Py_INCREF(res);
1802 }
1803 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001804 break;
1805 case 3:
1806 if (!PyArg_ParseTuple(args, "ssO:setvar",
1807 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001808 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001809 CHECK_STRING_LENGTH(name1);
1810 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001811 /* XXX must hold tcl lock already??? */
1812 newval = AsObj(newValue);
1813 ENTER_TCL
1814 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1815 ENTER_OVERLAP
1816 if (!ok)
1817 Tkinter_Error(self);
1818 else {
1819 res = Py_None;
1820 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001821 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001822 LEAVE_OVERLAP_TCL
1823 break;
1824 default:
1825 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1826 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001827 }
1828 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001829}
1830
1831static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001832Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001833{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001834 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001835}
1836
1837static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001838Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001839{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001840 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001841}
1842
Barry Warsawfa701a81997-01-16 00:15:11 +00001843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001844
Guido van Rossum18468821994-06-20 07:49:28 +00001845static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001846GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001847{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001848 const char *name1, *name2=NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001849 PyObject *res = NULL;
1850 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001851
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001852 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1853 varname_converter, &name1, &name2))
1854 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001855
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001856 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001857 ENTER_TCL
1858 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1859 ENTER_OVERLAP
1860 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001861 PyErr_SetString(Tkinter_TclError,
1862 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001863 } else {
1864 if (((TkappObject*)self)->wantobjects) {
1865 res = FromObj(self, tres);
1866 }
1867 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001868 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001869 }
1870 }
1871 LEAVE_OVERLAP_TCL
1872 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001873}
1874
1875static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001876Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001877{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001878 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001879}
1880
1881static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001882Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001883{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001884 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001885}
1886
Barry Warsawfa701a81997-01-16 00:15:11 +00001887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001888
Guido van Rossum18468821994-06-20 07:49:28 +00001889static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001890UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001891{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001892 char *name1, *name2=NULL;
1893 int code;
1894 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001895
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001896 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1897 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001898
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001899 CHECK_STRING_LENGTH(name1);
1900 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001901 ENTER_TCL
1902 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1903 ENTER_OVERLAP
1904 if (code == TCL_ERROR)
1905 res = Tkinter_Error(self);
1906 else {
1907 Py_INCREF(Py_None);
1908 res = Py_None;
1909 }
1910 LEAVE_OVERLAP_TCL
1911 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001912}
1913
1914static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001915Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001916{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001917 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001918}
1919
1920static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001921Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001922{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001923 return var_invoke(UnsetVar, self, args,
1924 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001925}
1926
Barry Warsawfa701a81997-01-16 00:15:11 +00001927
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001928
Guido van Rossum18468821994-06-20 07:49:28 +00001929/** Tcl to Python **/
1930
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001931/*[clinic input]
1932_tkinter.tkapp.getint
1933
1934 arg: object
1935 /
1936
1937[clinic start generated code]*/
1938
Guido van Rossum18468821994-06-20 07:49:28 +00001939static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001940_tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
1941/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001942{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001943 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001944 Tcl_Obj *value;
1945 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00001946
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001947 if (PyLong_Check(arg)) {
1948 Py_INCREF(arg);
1949 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001950 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001951
Serhiy Storchaka645058d2015-05-06 14:00:04 +03001952 if (PyTclObject_Check(arg)) {
1953 value = ((PyTclObject*)arg)->value;
1954 Tcl_IncrRefCount(value);
1955 }
1956 else {
1957 if (!PyArg_Parse(arg, "s:getint", &s))
1958 return NULL;
1959 CHECK_STRING_LENGTH(s);
1960 value = Tcl_NewStringObj(s, -1);
1961 if (value == NULL)
1962 return Tkinter_Error((PyObject *)self);
1963 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001964 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
1965 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
1966
1967 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
1968 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
1969 */
1970#ifdef HAVE_LIBTOMMAMTH
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001971 result = fromBignumObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001972#else
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001973 result = fromWideIntObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001974#endif
1975 Tcl_DecrRefCount(value);
1976 if (result != NULL || PyErr_Occurred())
1977 return result;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001978 return Tkinter_Error((PyObject *)self);
Guido van Rossum18468821994-06-20 07:49:28 +00001979}
1980
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001981/*[clinic input]
1982_tkinter.tkapp.getdouble
1983
1984 arg: object
1985 /
1986
1987[clinic start generated code]*/
1988
Guido van Rossum18468821994-06-20 07:49:28 +00001989static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001990_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
1991/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001992{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001993 char *s;
1994 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001995
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001996 if (PyFloat_Check(arg)) {
1997 Py_INCREF(arg);
1998 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001999 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002000
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002001 if (PyNumber_Check(arg)) {
2002 return PyNumber_Float(arg);
2003 }
2004
2005 if (PyTclObject_Check(arg)) {
2006 if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
2007 ((PyTclObject*)arg)->value,
2008 &v) == TCL_ERROR)
2009 return Tkinter_Error((PyObject *)self);
2010 return PyFloat_FromDouble(v);
2011 }
2012
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002013 if (!PyArg_Parse(arg, "s:getdouble", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002014 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002015 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002016 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002017 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002018 return PyFloat_FromDouble(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002019}
2020
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002021/*[clinic input]
2022_tkinter.tkapp.getboolean
2023
2024 arg: object
2025 /
2026
2027[clinic start generated code]*/
2028
Guido van Rossum18468821994-06-20 07:49:28 +00002029static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002030_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
2031/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002032{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002033 char *s;
2034 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002035
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002036 if (PyLong_Check(arg)) { /* int or bool */
2037 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002038 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002039
2040 if (PyTclObject_Check(arg)) {
2041 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2042 ((PyTclObject*)arg)->value,
2043 &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002044 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002045 return PyBool_FromLong(v);
2046 }
2047
2048 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002049 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002050 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002051 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002052 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002053 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002054}
2055
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002056/*[clinic input]
2057_tkinter.tkapp.exprstring
2058
2059 s: str
2060 /
2061
2062[clinic start generated code]*/
2063
Guido van Rossum18468821994-06-20 07:49:28 +00002064static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002065_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2066/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002067{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002068 PyObject *res = NULL;
2069 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002070
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002071 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002072 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002073
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002074 ENTER_TCL
2075 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2076 ENTER_OVERLAP
2077 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002078 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002079 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002080 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002081 LEAVE_OVERLAP_TCL
2082 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002083}
2084
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002085/*[clinic input]
2086_tkinter.tkapp.exprlong
2087
2088 s: str
2089 /
2090
2091[clinic start generated code]*/
2092
Guido van Rossum18468821994-06-20 07:49:28 +00002093static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002094_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2095/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002096{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002097 PyObject *res = NULL;
2098 int retval;
2099 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002100
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002101 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002102 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002104 ENTER_TCL
2105 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2106 ENTER_OVERLAP
2107 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002108 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002109 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002110 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002111 LEAVE_OVERLAP_TCL
2112 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002113}
2114
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002115/*[clinic input]
2116_tkinter.tkapp.exprdouble
2117
2118 s: str
2119 /
2120
2121[clinic start generated code]*/
2122
Guido van Rossum18468821994-06-20 07:49:28 +00002123static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002124_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2125/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002126{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002127 PyObject *res = NULL;
2128 double v;
2129 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002130
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002131 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002132 CHECK_TCL_APPARTMENT;
2133 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2134 ENTER_TCL
2135 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2136 ENTER_OVERLAP
2137 PyFPE_END_PROTECT(retval)
2138 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002139 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002140 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002141 res = PyFloat_FromDouble(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142 LEAVE_OVERLAP_TCL
2143 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002144}
2145
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002146/*[clinic input]
2147_tkinter.tkapp.exprboolean
2148
2149 s: str
2150 /
2151
2152[clinic start generated code]*/
2153
Guido van Rossum18468821994-06-20 07:49:28 +00002154static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002155_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2156/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002157{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002158 PyObject *res = NULL;
2159 int retval;
2160 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002161
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002162 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002163 CHECK_TCL_APPARTMENT;
2164 ENTER_TCL
2165 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2166 ENTER_OVERLAP
2167 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002168 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002169 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002170 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002171 LEAVE_OVERLAP_TCL
2172 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002173}
2174
Barry Warsawfa701a81997-01-16 00:15:11 +00002175
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002176
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002177/*[clinic input]
2178_tkinter.tkapp.splitlist
2179
2180 arg: object
2181 /
2182
2183[clinic start generated code]*/
2184
Guido van Rossum18468821994-06-20 07:49:28 +00002185static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002186_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2187/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002188{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002189 char *list;
2190 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002191 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002192 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002193 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002194
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002195 if (PyTclObject_Check(arg)) {
2196 int objc;
2197 Tcl_Obj **objv;
2198 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2199 ((PyTclObject*)arg)->value,
2200 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002201 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002202 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002203 if (!(v = PyTuple_New(objc)))
2204 return NULL;
2205 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002206 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002207 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002208 Py_DECREF(v);
2209 return NULL;
2210 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002211 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002212 }
2213 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002214 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002215 if (PyTuple_Check(arg)) {
2216 Py_INCREF(arg);
2217 return arg;
2218 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002219 if (PyList_Check(arg)) {
2220 return PySequence_Tuple(arg);
2221 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002222
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002223 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002224 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002225
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002226 if (strlen(list) >= INT_MAX) {
2227 PyErr_SetString(PyExc_OverflowError, "string is too long");
2228 PyMem_Free(list);
2229 return NULL;
2230 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002231 if (Tcl_SplitList(Tkapp_Interp(self), list,
2232 &argc, &argv) == TCL_ERROR) {
2233 PyMem_Free(list);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002234 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002235 }
Guido van Rossum18468821994-06-20 07:49:28 +00002236
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002237 if (!(v = PyTuple_New(argc)))
2238 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002239
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002240 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002241 PyObject *s = unicodeFromTclString(argv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002242 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002243 Py_DECREF(v);
2244 v = NULL;
2245 goto finally;
2246 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002247 PyTuple_SET_ITEM(v, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002248 }
Guido van Rossum18468821994-06-20 07:49:28 +00002249
Barry Warsawfa701a81997-01-16 00:15:11 +00002250 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002251 ckfree(FREECAST argv);
2252 PyMem_Free(list);
2253 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002254}
2255
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002256/*[clinic input]
2257_tkinter.tkapp.split
2258
2259 arg: object
2260 /
2261
2262[clinic start generated code]*/
2263
Guido van Rossum18468821994-06-20 07:49:28 +00002264static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002265_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2266/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002267{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002268 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002269 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002270
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002271 if (PyTclObject_Check(arg)) {
2272 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2273 int objc;
2274 Tcl_Obj **objv;
2275 int i;
2276 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2277 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002278 return FromObj((PyObject*)self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002279 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002280 if (objc == 0)
2281 return PyUnicode_FromString("");
2282 if (objc == 1)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002283 return FromObj((PyObject*)self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002284 if (!(v = PyTuple_New(objc)))
2285 return NULL;
2286 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002287 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002288 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002289 Py_DECREF(v);
2290 return NULL;
2291 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002292 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002293 }
2294 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002295 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002296 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002297 return SplitObj(arg);
2298
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002299 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002300 return NULL;
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002301 if (strlen(list) >= INT_MAX) {
2302 PyErr_SetString(PyExc_OverflowError, "string is too long");
2303 PyMem_Free(list);
2304 return NULL;
2305 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002306 v = Split(list);
2307 PyMem_Free(list);
2308 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002309}
2310
Barry Warsawfa701a81997-01-16 00:15:11 +00002311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002312
Guido van Rossum18468821994-06-20 07:49:28 +00002313/** Tcl Command **/
2314
Guido van Rossum00d93061998-05-28 23:06:38 +00002315/* Client data struct */
2316typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002317 PyObject *self;
2318 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002319} PythonCmd_ClientData;
2320
2321static int
Fred Drake509d79a2000-07-08 04:04:38 +00002322PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002323{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002324 errorInCmd = 1;
2325 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2326 LEAVE_PYTHON
2327 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002328}
2329
Guido van Rossum18468821994-06-20 07:49:28 +00002330/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002331 * function or method.
2332 */
Guido van Rossum18468821994-06-20 07:49:28 +00002333static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002334PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002335{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002336 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002337 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002338 int i, rv;
2339 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002340
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002341 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002343 /* TBD: no error checking here since we know, via the
2344 * Tkapp_CreateCommand() that the client data is a two-tuple
2345 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002346 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002348 /* Create argument list (argv1, ..., argvN) */
2349 if (!(arg = PyTuple_New(argc - 1)))
2350 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002352 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002353 PyObject *s = unicodeFromTclString(argv[i + 1]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002354 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002355 Py_DECREF(arg);
2356 return PythonCmd_Error(interp);
2357 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002358 PyTuple_SET_ITEM(arg, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002359 }
INADA Naoki72dccde2017-02-16 09:26:01 +09002360 res = PyObject_Call(func, arg, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002361 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002362
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002363 if (res == NULL)
2364 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002366 obj_res = AsObj(res);
2367 if (obj_res == NULL) {
2368 Py_DECREF(res);
2369 return PythonCmd_Error(interp);
2370 }
2371 else {
2372 Tcl_SetObjResult(interp, obj_res);
2373 rv = TCL_OK;
2374 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002376 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002377
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002378 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002380 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002381}
2382
2383static void
Fred Drake509d79a2000-07-08 04:04:38 +00002384PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002385{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002386 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002388 ENTER_PYTHON
2389 Py_XDECREF(data->self);
2390 Py_XDECREF(data->func);
2391 PyMem_DEL(data);
2392 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002393}
2394
Barry Warsawfa701a81997-01-16 00:15:11 +00002395
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002396
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002397
2398TCL_DECLARE_MUTEX(command_mutex)
2399
2400typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002401 Tcl_Event ev;
2402 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002403 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002404 int create;
2405 int *status;
2406 ClientData *data;
2407 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002408} CommandEvent;
2409
2410static int
2411Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002412{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002413 if (ev->create)
2414 *ev->status = Tcl_CreateCommand(
2415 ev->interp, ev->name, PythonCmd,
2416 ev->data, PythonCmdDelete) == NULL;
2417 else
2418 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2419 Tcl_MutexLock(&command_mutex);
2420 Tcl_ConditionNotify(ev->done);
2421 Tcl_MutexUnlock(&command_mutex);
2422 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002423}
2424
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002425/*[clinic input]
2426_tkinter.tkapp.createcommand
2427
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002428 name: str
2429 func: object
2430 /
2431
2432[clinic start generated code]*/
2433
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002434static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002435_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2436 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002437/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002438{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002439 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002440 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002441
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002442 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002443 if (!PyCallable_Check(func)) {
2444 PyErr_SetString(PyExc_TypeError, "command not callable");
2445 return NULL;
2446 }
Guido van Rossum18468821994-06-20 07:49:28 +00002447
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002448 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2449 !WaitForMainloop(self))
2450 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002451
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002452 data = PyMem_NEW(PythonCmd_ClientData, 1);
2453 if (!data)
2454 return PyErr_NoMemory();
2455 Py_INCREF(self);
2456 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002457 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002458 data->func = func;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002459 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2460 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002461 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2462 if (ev == NULL) {
2463 PyErr_NoMemory();
2464 PyMem_DEL(data);
2465 return NULL;
2466 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002467 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2468 ev->interp = self->interp;
2469 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002470 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 ev->data = (ClientData)data;
2472 ev->status = &err;
2473 ev->done = &cond;
2474 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2475 Tcl_ConditionFinalize(&cond);
2476 }
2477 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002478 {
2479 ENTER_TCL
2480 err = Tcl_CreateCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002481 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002482 (ClientData)data, PythonCmdDelete) == NULL;
2483 LEAVE_TCL
2484 }
2485 if (err) {
2486 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2487 PyMem_DEL(data);
2488 return NULL;
2489 }
Guido van Rossum18468821994-06-20 07:49:28 +00002490
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002491 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002492}
2493
Barry Warsawfa701a81997-01-16 00:15:11 +00002494
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002495
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002496/*[clinic input]
2497_tkinter.tkapp.deletecommand
2498
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002499 name: str
2500 /
2501
2502[clinic start generated code]*/
2503
Guido van Rossum18468821994-06-20 07:49:28 +00002504static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002505_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002506/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002507{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002509
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002510 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002512 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2513 Tcl_Condition cond = NULL;
2514 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002515 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2516 if (ev == NULL) {
2517 PyErr_NoMemory();
2518 return NULL;
2519 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002520 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2521 ev->interp = self->interp;
2522 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002523 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002524 ev->status = &err;
2525 ev->done = &cond;
2526 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2527 &command_mutex);
2528 Tcl_ConditionFinalize(&cond);
2529 }
2530 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002531 {
2532 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002533 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002534 LEAVE_TCL
2535 }
2536 if (err == -1) {
2537 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2538 return NULL;
2539 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002540 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002541}
2542
Barry Warsawfa701a81997-01-16 00:15:11 +00002543
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002544
Guido van Rossum00d93061998-05-28 23:06:38 +00002545#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002546/** File Handler **/
2547
Guido van Rossum00d93061998-05-28 23:06:38 +00002548typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002549 PyObject *func;
2550 PyObject *file;
2551 int id;
2552 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002553} FileHandler_ClientData;
2554
2555static FileHandler_ClientData *HeadFHCD;
2556
2557static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002558NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002559{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560 FileHandler_ClientData *p;
2561 p = PyMem_NEW(FileHandler_ClientData, 1);
2562 if (p != NULL) {
2563 Py_XINCREF(func);
2564 Py_XINCREF(file);
2565 p->func = func;
2566 p->file = file;
2567 p->id = id;
2568 p->next = HeadFHCD;
2569 HeadFHCD = p;
2570 }
2571 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002572}
2573
2574static void
Fred Drake509d79a2000-07-08 04:04:38 +00002575DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002576{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002577 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579 pp = &HeadFHCD;
2580 while ((p = *pp) != NULL) {
2581 if (p->id == id) {
2582 *pp = p->next;
2583 Py_XDECREF(p->func);
2584 Py_XDECREF(p->file);
2585 PyMem_DEL(p);
2586 }
2587 else
2588 pp = &p->next;
2589 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002590}
2591
Guido van Rossuma597dde1995-01-10 20:56:29 +00002592static void
Fred Drake509d79a2000-07-08 04:04:38 +00002593FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002594{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002595 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
INADA Naoki72dccde2017-02-16 09:26:01 +09002596 PyObject *func, *file, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002598 ENTER_PYTHON
2599 func = data->func;
2600 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002601
INADA Naoki72dccde2017-02-16 09:26:01 +09002602 res = PyObject_CallFunction(func, "Oi", file, mask);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002603 if (res == NULL) {
2604 errorInCmd = 1;
2605 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2606 }
2607 Py_XDECREF(res);
2608 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002609}
2610
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002611/*[clinic input]
2612_tkinter.tkapp.createfilehandler
2613
2614 file: object
2615 mask: int
2616 func: object
2617 /
2618
2619[clinic start generated code]*/
2620
Guido van Rossum18468821994-06-20 07:49:28 +00002621static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002622_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2623 int mask, PyObject *func)
2624/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002625{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002626 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002627 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002628
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002629 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002631 tfile = PyObject_AsFileDescriptor(file);
2632 if (tfile < 0)
2633 return NULL;
2634 if (!PyCallable_Check(func)) {
2635 PyErr_SetString(PyExc_TypeError, "bad argument list");
2636 return NULL;
2637 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002638
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002639 data = NewFHCD(func, file, tfile);
2640 if (data == NULL)
2641 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002643 /* Ought to check for null Tcl_File object... */
2644 ENTER_TCL
2645 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2646 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002647 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002648}
2649
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002650/*[clinic input]
2651_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002652
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002653 file: object
2654 /
2655
2656[clinic start generated code]*/
2657
2658static PyObject *
2659_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2660/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2661{
2662 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002664 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002666 tfile = PyObject_AsFileDescriptor(file);
2667 if (tfile < 0)
2668 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002670 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002672 /* Ought to check for null Tcl_File object... */
2673 ENTER_TCL
2674 Tcl_DeleteFileHandler(tfile);
2675 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002676 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002677}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002678#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002679
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002680
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002681/**** Tktt Object (timer token) ****/
2682
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002683static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002684
Guido van Rossum00d93061998-05-28 23:06:38 +00002685typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002686 PyObject_HEAD
2687 Tcl_TimerToken token;
2688 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002689} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002690
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002691/*[clinic input]
2692_tkinter.tktimertoken.deletetimerhandler
2693
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002694[clinic start generated code]*/
2695
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002696static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002697_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002698/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002699{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002700 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002701 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002702
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002703 if (v->token != NULL) {
2704 Tcl_DeleteTimerHandler(v->token);
2705 v->token = NULL;
2706 }
2707 if (func != NULL) {
2708 v->func = NULL;
2709 Py_DECREF(func);
2710 Py_DECREF(v); /* See Tktt_New() */
2711 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002712 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002713}
2714
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002715static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002716Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002717{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002718 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002719
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002720 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002721 if (v == NULL)
2722 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002723
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002724 Py_INCREF(func);
2725 v->token = NULL;
2726 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002727
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002728 /* Extra reference, deleted when called or when handler is deleted */
2729 Py_INCREF(v);
2730 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002731}
2732
2733static void
Fred Drake509d79a2000-07-08 04:04:38 +00002734Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002735{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002736 TkttObject *v = (TkttObject *)self;
2737 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002738 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002739
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002740 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002741
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002742 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002743 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002744}
2745
Guido van Rossum597ac201998-05-12 14:36:19 +00002746static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002747Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002748{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002749 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002750 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2751 v,
2752 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002753}
2754
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002755/** Timer Handler **/
2756
2757static void
Fred Drake509d79a2000-07-08 04:04:38 +00002758TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002759{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002760 TkttObject *v = (TkttObject *)clientData;
2761 PyObject *func = v->func;
2762 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002763
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002764 if (func == NULL)
2765 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002766
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002767 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002769 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002770
INADA Naoki72dccde2017-02-16 09:26:01 +09002771 res = _PyObject_CallNoArg(func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002772 Py_DECREF(func);
2773 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002774
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002775 if (res == NULL) {
2776 errorInCmd = 1;
2777 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2778 }
2779 else
2780 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002781
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002782 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002783}
2784
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002785/*[clinic input]
2786_tkinter.tkapp.createtimerhandler
2787
2788 milliseconds: int
2789 func: object
2790 /
2791
2792[clinic start generated code]*/
2793
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002794static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002795_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2796 PyObject *func)
2797/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002798{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002799 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002800
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002801 if (!PyCallable_Check(func)) {
2802 PyErr_SetString(PyExc_TypeError, "bad argument list");
2803 return NULL;
2804 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002805
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002806 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002807
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002808 v = Tktt_New(func);
2809 if (v) {
2810 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2811 (ClientData)v);
2812 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002813
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002814 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002815}
2816
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002817
Guido van Rossum18468821994-06-20 07:49:28 +00002818/** Event Loop **/
2819
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002820/*[clinic input]
2821_tkinter.tkapp.mainloop
2822
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002823 threshold: int = 0
2824 /
2825
2826[clinic start generated code]*/
2827
Guido van Rossum18468821994-06-20 07:49:28 +00002828static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002829_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002830/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002831{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002832 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002833
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002834 CHECK_TCL_APPARTMENT;
2835 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002837 quitMainLoop = 0;
2838 while (Tk_GetNumMainWindows() > threshold &&
2839 !quitMainLoop &&
2840 !errorInCmd)
2841 {
2842 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002844 if (self->threaded) {
2845 /* Allow other Python threads to run. */
2846 ENTER_TCL
2847 result = Tcl_DoOneEvent(0);
2848 LEAVE_TCL
2849 }
2850 else {
2851 Py_BEGIN_ALLOW_THREADS
2852 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2853 tcl_tstate = tstate;
2854 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2855 tcl_tstate = NULL;
2856 if(tcl_lock)PyThread_release_lock(tcl_lock);
2857 if (result == 0)
2858 Sleep(Tkinter_busywaitinterval);
2859 Py_END_ALLOW_THREADS
2860 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002861
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002862 if (PyErr_CheckSignals() != 0) {
2863 self->dispatching = 0;
2864 return NULL;
2865 }
2866 if (result < 0)
2867 break;
2868 }
2869 self->dispatching = 0;
2870 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002871
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002872 if (errorInCmd) {
2873 errorInCmd = 0;
2874 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2875 excInCmd = valInCmd = trbInCmd = NULL;
2876 return NULL;
2877 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002878 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002879}
2880
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002881/*[clinic input]
2882_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002883
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002884 flags: int = 0
2885 /
2886
2887[clinic start generated code]*/
2888
2889static PyObject *
2890_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2891/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2892{
2893 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002894
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002895 ENTER_TCL
2896 rv = Tcl_DoOneEvent(flags);
2897 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002898 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002899}
2900
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002901/*[clinic input]
2902_tkinter.tkapp.quit
2903[clinic start generated code]*/
2904
Guido van Rossum062cfb01995-01-10 17:42:51 +00002905static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002906_tkinter_tkapp_quit_impl(TkappObject *self)
2907/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002908{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002909 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002910 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002911}
2912
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002913/*[clinic input]
2914_tkinter.tkapp.interpaddr
2915[clinic start generated code]*/
2916
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002917static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002918_tkinter_tkapp_interpaddr_impl(TkappObject *self)
2919/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002920{
Victor Stinnere1040e22013-09-05 00:22:24 +02002921 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002922}
2923
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002924/*[clinic input]
2925_tkinter.tkapp.loadtk
2926[clinic start generated code]*/
2927
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002928static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002929_tkinter_tkapp_loadtk_impl(TkappObject *self)
2930/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00002931{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002932 Tcl_Interp *interp = Tkapp_Interp(self);
2933 const char * _tk_exists = NULL;
2934 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002935
Guilherme Polob681df42009-02-09 22:33:59 +00002936#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002937 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2938 * first call failed.
2939 * To avoid the deadlock, we just refuse the second call through
2940 * a static variable.
2941 */
2942 if (tk_load_failed) {
2943 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2944 return NULL;
2945 }
Guilherme Polob681df42009-02-09 22:33:59 +00002946#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002947
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002948 /* We want to guard against calling Tk_Init() multiple times */
2949 CHECK_TCL_APPARTMENT;
2950 ENTER_TCL
2951 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2952 ENTER_OVERLAP
2953 if (err == TCL_ERROR) {
2954 /* This sets an exception, but we cannot return right
2955 away because we need to exit the overlap first. */
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002956 Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002957 } else {
2958 _tk_exists = Tkapp_Result(self);
2959 }
2960 LEAVE_OVERLAP_TCL
2961 if (err == TCL_ERROR) {
2962 return NULL;
2963 }
2964 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2965 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002966 PyErr_SetString(Tkinter_TclError,
2967 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002968#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002969 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002970#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002971 return NULL;
2972 }
2973 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002974 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002975}
Barry Warsawfa701a81997-01-16 00:15:11 +00002976
Martin v. Löwisffad6332002-11-26 09:28:05 +00002977static PyObject *
2978Tkapp_WantObjects(PyObject *self, PyObject *args)
2979{
2980
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002981 int wantobjects = -1;
2982 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2983 return NULL;
2984 if (wantobjects == -1)
2985 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2986 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002987
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002988 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002989}
2990
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002991/*[clinic input]
2992_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002993
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002994[clinic start generated code]*/
2995
2996static PyObject *
2997_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002998/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002999{
3000 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003001
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003002 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003003}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003004
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003005
Guido van Rossum18468821994-06-20 07:49:28 +00003006/**** Tkapp Type Methods ****/
3007
3008static void
Fred Drake509d79a2000-07-08 04:04:38 +00003009Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003010{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003011 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003012 /*CHECK_TCL_APPARTMENT;*/
3013 ENTER_TCL
3014 Tcl_DeleteInterp(Tkapp_Interp(self));
3015 LEAVE_TCL
3016 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003017 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003018 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003019}
3020
Barry Warsawfa701a81997-01-16 00:15:11 +00003021
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003022
Guido van Rossum18468821994-06-20 07:49:28 +00003023/**** Tkinter Module ****/
3024
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003025typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003026 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003027 Py_ssize_t size; /* current size */
3028 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003029} FlattenContext;
3030
3031static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003032_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003033{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003034 /* expand tuple to hold (at least) size new items.
3035 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003036
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003037 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003038
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003039 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003040 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003041
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003042 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003043
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003044 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003045}
3046
3047static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003048_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003049{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003050 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003051
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003052 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003053
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003054 if (depth > 1000) {
3055 PyErr_SetString(PyExc_ValueError,
3056 "nesting too deep in _flatten");
3057 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003058 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3059 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003060 /* preallocate (assume no nesting) */
3061 if (context->size + size > context->maxsize &&
3062 !_bump(context, size))
3063 return 0;
3064 /* copy items to output tuple */
3065 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003066 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003067 if (PyList_Check(o) || PyTuple_Check(o)) {
3068 if (!_flatten1(context, o, depth + 1))
3069 return 0;
3070 } else if (o != Py_None) {
3071 if (context->size + 1 > context->maxsize &&
3072 !_bump(context, 1))
3073 return 0;
3074 Py_INCREF(o);
3075 PyTuple_SET_ITEM(context->tuple,
3076 context->size++, o);
3077 }
3078 }
3079 } else {
3080 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3081 return 0;
3082 }
3083 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003084}
3085
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003086/*[clinic input]
3087_tkinter._flatten
3088
3089 item: object
3090 /
3091
3092[clinic start generated code]*/
3093
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003094static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003095_tkinter__flatten(PyObject *module, PyObject *item)
3096/*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003097{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003098 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003099
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003100 context.maxsize = PySequence_Size(item);
3101 if (context.maxsize < 0)
3102 return NULL;
3103 if (context.maxsize == 0)
3104 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003105
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003106 context.tuple = PyTuple_New(context.maxsize);
3107 if (!context.tuple)
3108 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003109
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003110 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003112 if (!_flatten1(&context, item,0))
3113 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003114
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003115 if (_PyTuple_Resize(&context.tuple, context.size))
3116 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003118 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003119}
3120
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003121/*[clinic input]
3122_tkinter.create
3123
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003124 screenName: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003125 baseName: str = NULL
3126 className: str = "Tk"
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003127 interactive: bool(accept={int}) = False
3128 wantobjects: bool(accept={int}) = False
3129 wantTk: bool(accept={int}) = True
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003130 if false, then Tk_Init() doesn't get called
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003131 sync: bool(accept={int}) = False
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003132 if true, then pass -sync to wish
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003133 use: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003134 if not None, then pass -use to wish
3135 /
3136
3137[clinic start generated code]*/
3138
Guido van Rossum18468821994-06-20 07:49:28 +00003139static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003140_tkinter_create_impl(PyObject *module, const char *screenName,
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003141 const char *baseName, const char *className,
3142 int interactive, int wantobjects, int wantTk, int sync,
3143 const char *use)
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003144/*[clinic end generated code: output=e3315607648e6bb4 input=431907c134c80085]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003145{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003146 /* XXX baseName is not used anymore;
3147 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003148 CHECK_STRING_LENGTH(screenName);
3149 CHECK_STRING_LENGTH(baseName);
3150 CHECK_STRING_LENGTH(className);
3151 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003152
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003153 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003154 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003155 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003156}
3157
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003158/*[clinic input]
3159_tkinter.setbusywaitinterval
3160
3161 new_val: int
3162 /
3163
3164Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3165
3166It should be set to a divisor of the maximum time between frames in an animation.
3167[clinic start generated code]*/
3168
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003169static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003170_tkinter_setbusywaitinterval_impl(PyObject *module, int new_val)
3171/*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003172{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003173 if (new_val < 0) {
3174 PyErr_SetString(PyExc_ValueError,
3175 "busywaitinterval must be >= 0");
3176 return NULL;
3177 }
3178 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003179 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003180}
3181
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003182/*[clinic input]
3183_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003184
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003185Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3186[clinic start generated code]*/
3187
3188static int
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003189_tkinter_getbusywaitinterval_impl(PyObject *module)
3190/*[clinic end generated code: output=23b72d552001f5c7 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003191{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003192 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003193}
3194
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003195#include "clinic/_tkinter.c.h"
3196
3197static PyMethodDef Tktt_methods[] =
3198{
3199 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3200 {NULL, NULL}
3201};
3202
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003203static PyType_Slot Tktt_Type_slots[] = {
3204 {Py_tp_dealloc, Tktt_Dealloc},
3205 {Py_tp_repr, Tktt_Repr},
3206 {Py_tp_methods, Tktt_methods},
3207 {0, 0}
3208};
3209
3210static PyType_Spec Tktt_Type_spec = {
3211 "_tkinter.tktimertoken",
3212 sizeof(TkttObject),
3213 0,
3214 Py_TPFLAGS_DEFAULT,
3215 Tktt_Type_slots,
3216};
3217
3218
3219/**** Tkapp Method List ****/
3220
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003221static PyMethodDef Tkapp_methods[] =
3222{
3223 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3224 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3225 {"call", Tkapp_Call, METH_VARARGS},
3226 _TKINTER_TKAPP_EVAL_METHODDEF
3227 _TKINTER_TKAPP_EVALFILE_METHODDEF
3228 _TKINTER_TKAPP_RECORD_METHODDEF
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03003229 _TKINTER_TKAPP_ADDERRORINFO_METHODDEF
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003230 {"setvar", Tkapp_SetVar, METH_VARARGS},
3231 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3232 {"getvar", Tkapp_GetVar, METH_VARARGS},
3233 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3234 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3235 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3236 _TKINTER_TKAPP_GETINT_METHODDEF
3237 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3238 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3239 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3240 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3241 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3242 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3243 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3244 _TKINTER_TKAPP_SPLIT_METHODDEF
3245 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3246 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3247 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3248 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3249 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3250 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3251 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3252 _TKINTER_TKAPP_QUIT_METHODDEF
3253 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3254 _TKINTER_TKAPP_LOADTK_METHODDEF
3255 {NULL, NULL}
3256};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003257
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003258static PyType_Slot Tkapp_Type_slots[] = {
3259 {Py_tp_dealloc, Tkapp_Dealloc},
3260 {Py_tp_methods, Tkapp_methods},
3261 {0, 0}
3262};
3263
3264
3265static PyType_Spec Tkapp_Type_spec = {
3266 "_tkinter.tkapp",
3267 sizeof(TkappObject),
3268 0,
3269 Py_TPFLAGS_DEFAULT,
3270 Tkapp_Type_slots,
3271};
3272
Guido van Rossum18468821994-06-20 07:49:28 +00003273static PyMethodDef moduleMethods[] =
3274{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003275 _TKINTER__FLATTEN_METHODDEF
3276 _TKINTER_CREATE_METHODDEF
3277 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3278 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003279 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003280};
3281
Guido van Rossum7bf15641998-05-22 18:28:17 +00003282#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003283
3284static int stdin_ready = 0;
3285
Guido van Rossumad4db171998-06-13 13:56:28 +00003286#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003287static void
Fred Drake509d79a2000-07-08 04:04:38 +00003288MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003289{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003290 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003291}
Guido van Rossumad4db171998-06-13 13:56:28 +00003292#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003293
Guido van Rossum00d93061998-05-28 23:06:38 +00003294static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003295
Guido van Rossum18468821994-06-20 07:49:28 +00003296static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003297EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003298{
Guido van Rossumad4db171998-06-13 13:56:28 +00003299#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003300 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003301#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003302 PyEval_RestoreThread(event_tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003303 stdin_ready = 0;
3304 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003305#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003306 tfile = fileno(stdin);
3307 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003308#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003309 while (!errorInCmd && !stdin_ready) {
3310 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003311#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003312 if (_kbhit()) {
3313 stdin_ready = 1;
3314 break;
3315 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003316#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003317 Py_BEGIN_ALLOW_THREADS
3318 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3319 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003321 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003322
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003323 tcl_tstate = NULL;
3324 if(tcl_lock)PyThread_release_lock(tcl_lock);
3325 if (result == 0)
3326 Sleep(Tkinter_busywaitinterval);
3327 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003328
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003329 if (result < 0)
3330 break;
3331 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003332#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003333 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003334#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003335 if (errorInCmd) {
3336 errorInCmd = 0;
3337 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3338 excInCmd = valInCmd = trbInCmd = NULL;
3339 PyErr_Print();
3340 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003341 PyEval_SaveThread();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003342 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003343}
Guido van Rossum18468821994-06-20 07:49:28 +00003344
Guido van Rossum00d93061998-05-28 23:06:38 +00003345#endif
3346
Guido van Rossum7bf15641998-05-22 18:28:17 +00003347static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003348EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003349{
Guido van Rossum00d93061998-05-28 23:06:38 +00003350#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003351 if (PyOS_InputHook == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003352 event_tstate = PyThreadState_Get();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003353 PyOS_InputHook = EventHook;
3354 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003355#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003356}
3357
3358static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003359DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003360{
Guido van Rossum00d93061998-05-28 23:06:38 +00003361#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003362 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3363 PyOS_InputHook = NULL;
3364 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003365#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003366}
3367
Barry Warsawfa701a81997-01-16 00:15:11 +00003368
Martin v. Löwis1a214512008-06-11 05:26:20 +00003369static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003370 PyModuleDef_HEAD_INIT,
3371 "_tkinter",
3372 NULL,
3373 -1,
3374 moduleMethods,
3375 NULL,
3376 NULL,
3377 NULL,
3378 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003379};
3380
Mark Hammond62b1ab12002-07-23 06:31:15 +00003381PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003382PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003383{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003384 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003385
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003386 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003387 if (tcl_lock == NULL)
3388 return NULL;
Guido van Rossumae92f011996-08-21 19:03:36 +00003389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003390 m = PyModule_Create(&_tkintermodule);
3391 if (m == NULL)
3392 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003393
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003394 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3395 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003396 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003397 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003398 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003399 Py_INCREF(o);
3400 if (PyModule_AddObject(m, "TclError", o)) {
3401 Py_DECREF(o);
3402 Py_DECREF(m);
3403 return NULL;
3404 }
3405 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003406
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003407 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3408 Py_DECREF(m);
3409 return NULL;
3410 }
3411 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3412 Py_DECREF(m);
3413 return NULL;
3414 }
3415 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3416 Py_DECREF(m);
3417 return NULL;
3418 }
3419 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3420 Py_DECREF(m);
3421 return NULL;
3422 }
3423 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3424 Py_DECREF(m);
3425 return NULL;
3426 }
3427 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3428 Py_DECREF(m);
3429 return NULL;
3430 }
3431 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3432 Py_DECREF(m);
3433 return NULL;
3434 }
3435 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3436 Py_DECREF(m);
3437 return NULL;
3438 }
3439 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3440 Py_DECREF(m);
3441 return NULL;
3442 }
3443 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3444 Py_DECREF(m);
3445 return NULL;
3446 }
3447 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3448 Py_DECREF(m);
3449 return NULL;
3450 }
3451
3452 o = PyType_FromSpec(&Tkapp_Type_spec);
3453 if (o == NULL) {
3454 Py_DECREF(m);
3455 return NULL;
3456 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003457 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003458 if (PyModule_AddObject(m, "TkappType", o)) {
3459 Py_DECREF(o);
3460 Py_DECREF(m);
3461 return NULL;
3462 }
3463 Tkapp_Type = o;
3464
3465 o = PyType_FromSpec(&Tktt_Type_spec);
3466 if (o == NULL) {
3467 Py_DECREF(m);
3468 return NULL;
3469 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003470 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003471 if (PyModule_AddObject(m, "TkttType", o)) {
3472 Py_DECREF(o);
3473 Py_DECREF(m);
3474 return NULL;
3475 }
3476 Tktt_Type = o;
3477
3478 o = PyType_FromSpec(&PyTclObject_Type_spec);
3479 if (o == NULL) {
3480 Py_DECREF(m);
3481 return NULL;
3482 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003483 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003484 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3485 Py_DECREF(o);
3486 Py_DECREF(m);
3487 return NULL;
3488 }
3489 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003490
3491#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003492 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3493 * start waking up. Note that Tcl_FindExecutable will do this, this
3494 * code must be above it! The original warning from
3495 * tkMacOSXAppInit.c is copied below.
3496 *
3497 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3498 * Tcl interpreter for now. It probably should work to do this
3499 * in the other order, but for now it doesn't seem to.
3500 *
3501 */
3502 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003503#endif
3504
3505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003506 /* This helps the dynamic loader; in Unicode aware Tcl versions
3507 it also helps Tcl find its encodings. */
3508 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3509 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003510 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003511 if (cexe) {
3512#ifdef MS_WINDOWS
3513 int set_var = 0;
3514 PyObject *str_path;
3515 wchar_t *wcs_path;
3516 DWORD ret;
3517
3518 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3519
3520 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3521 str_path = _get_tcl_lib_path();
3522 if (str_path == NULL && PyErr_Occurred()) {
3523 return NULL;
3524 }
3525 if (str_path != NULL) {
3526 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3527 if (wcs_path == NULL) {
3528 return NULL;
3529 }
3530 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3531 set_var = 1;
3532 }
3533 }
3534
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003535 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003536
3537 if (set_var) {
3538 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3539 PyMem_Free(wcs_path);
3540 }
3541#else
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003542 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003543#endif /* MS_WINDOWS */
3544 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003545 Py_XDECREF(cexe);
3546 Py_DECREF(uexe);
3547 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003548
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003549 if (PyErr_Occurred()) {
3550 Py_DECREF(m);
3551 return NULL;
3552 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003553
Guido van Rossum43ff8681998-07-14 18:02:13 +00003554#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003555 /* This was not a good idea; through <Destroy> bindings,
3556 Tcl_Finalize() may invoke Python code but at that point the
3557 interpreter and thread state have already been destroyed! */
3558 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003559#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003560 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003561}