blob: 005214e27f75b8028254661d80ea0d4071e13a94 [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, \
259 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 return 0; \
261 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000262
Guido van Rossum97867b21996-08-08 19:09:53 +0000263#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000264#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000265#endif
266
Guido van Rossum18468821994-06-20 07:49:28 +0000267/**** Tkapp Object Declaration ****/
268
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300269static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000270
Guido van Rossum00d93061998-05-28 23:06:38 +0000271typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000272 PyObject_HEAD
273 Tcl_Interp *interp;
274 int wantobjects;
275 int threaded; /* True if tcl_platform[threaded] */
276 Tcl_ThreadId thread_id;
277 int dispatching;
278 /* We cannot include tclInt.h, as this is internal.
279 So we cache interesting types here. */
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200280 const Tcl_ObjType *OldBooleanType;
Zachary Ware037605b2014-08-05 11:54:34 -0500281 const Tcl_ObjType *BooleanType;
282 const Tcl_ObjType *ByteArrayType;
283 const Tcl_ObjType *DoubleType;
284 const Tcl_ObjType *IntType;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300285 const Tcl_ObjType *WideIntType;
286 const Tcl_ObjType *BignumType;
Zachary Ware037605b2014-08-05 11:54:34 -0500287 const Tcl_ObjType *ListType;
288 const Tcl_ObjType *ProcBodyType;
289 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000290} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000291
Guido van Rossum18468821994-06-20 07:49:28 +0000292#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000293#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000294
Guido van Rossum35d43371997-08-02 00:09:09 +0000295#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000296(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000297
Barry Warsawfa701a81997-01-16 00:15:11 +0000298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000299
Guido van Rossum18468821994-06-20 07:49:28 +0000300/**** Error Handling ****/
301
302static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000303static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000304static int errorInCmd = 0;
305static PyObject *excInCmd;
306static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000307static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000308
Guilherme Polob681df42009-02-09 22:33:59 +0000309#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000310static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000311#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000313
Guido van Rossum18468821994-06-20 07:49:28 +0000314static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000315Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000316{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000317 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
318 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000319}
320
Barry Warsawfa701a81997-01-16 00:15:11 +0000321
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000322
Guido van Rossum18468821994-06-20 07:49:28 +0000323/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000324
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000325static int Tkinter_busywaitinterval = 20;
326
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000327#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000328
Guido van Rossum00d93061998-05-28 23:06:38 +0000329/* Millisecond sleep() for Unix platforms. */
330
331static void
Fred Drake509d79a2000-07-08 04:04:38 +0000332Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000333{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334 /* XXX Too bad if you don't have select(). */
335 struct timeval t;
336 t.tv_sec = milli/1000;
337 t.tv_usec = (milli%1000) * 1000;
338 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000339}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000340#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000341
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000342/* Wait up to 1s for the mainloop to come up. */
343
344static int
345WaitForMainloop(TkappObject* self)
346{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000347 int i;
348 for (i = 0; i < 10; i++) {
349 if (self->dispatching)
350 return 1;
351 Py_BEGIN_ALLOW_THREADS
352 Sleep(100);
353 Py_END_ALLOW_THREADS
354 }
355 if (self->dispatching)
356 return 1;
357 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
358 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000359}
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362
Guido van Rossum18468821994-06-20 07:49:28 +0000363#define ARGSZ 64
364
Barry Warsawfa701a81997-01-16 00:15:11 +0000365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000366
Guido van Rossum18468821994-06-20 07:49:28 +0000367static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200368unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
369{
370 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
371 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
372 /* Tcl encodes null character as \xc0\x80 */
373 if (memchr(s, '\xc0', size)) {
374 char *buf, *q;
375 const char *e = s + size;
376 PyErr_Clear();
377 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300378 if (buf == NULL) {
379 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200380 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300381 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200382 while (s != e) {
383 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
384 *q++ = '\0';
385 s += 2;
386 }
387 else
388 *q++ = *s++;
389 }
390 s = buf;
391 size = q - s;
392 r = PyUnicode_DecodeUTF8(s, size, NULL);
393 PyMem_Free(buf);
394 }
395 }
396 return r;
397}
398
399static PyObject *
400unicodeFromTclString(const char *s)
401{
402 return unicodeFromTclStringAndSize(s, strlen(s));
403}
404
405static PyObject *
406unicodeFromTclObj(Tcl_Obj *value)
407{
408 int len;
409 char *s = Tcl_GetStringFromObj(value, &len);
410 return unicodeFromTclStringAndSize(s, len);
411}
412
413
414static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300415Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000416{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000417 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300418 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000419 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000421 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300422 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 }
Guido van Rossum18468821994-06-20 07:49:28 +0000424
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000425 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
426 /* Not a list.
427 * Could be a quoted string containing funnies, e.g. {"}.
428 * Return the string itself.
429 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200430 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000431 }
Guido van Rossum18468821994-06-20 07:49:28 +0000432
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000433 if (argc == 0)
434 v = PyUnicode_FromString("");
435 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200436 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000437 else if ((v = PyTuple_New(argc)) != NULL) {
438 int i;
439 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000441 for (i = 0; i < argc; i++) {
442 if ((w = Split(argv[i])) == NULL) {
443 Py_DECREF(v);
444 v = NULL;
445 break;
446 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300447 PyTuple_SET_ITEM(v, i, w);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000448 }
449 }
450 Tcl_Free(FREECAST argv);
451 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000452}
453
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300454/* In some cases, Tcl will still return strings that are supposed to
455 be lists. SplitObj walks through a nested tuple, finding string
456 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000457
Martin v. Löwis59683e82008-06-13 07:50:45 +0000458static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000459SplitObj(PyObject *arg)
460{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 if (PyTuple_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200462 Py_ssize_t i, size;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000463 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000464
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300465 size = PyTuple_GET_SIZE(arg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 result = NULL;
467 /* Recursively invoke SplitObj for all tuple items.
468 If this does not return a new object, no action is
469 needed. */
470 for(i = 0; i < size; i++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300471 elem = PyTuple_GET_ITEM(arg, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000472 newelem = SplitObj(elem);
473 if (!newelem) {
474 Py_XDECREF(result);
475 return NULL;
476 }
477 if (!result) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200478 Py_ssize_t k;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000479 if (newelem == elem) {
480 Py_DECREF(newelem);
481 continue;
482 }
483 result = PyTuple_New(size);
484 if (!result)
485 return NULL;
486 for(k = 0; k < i; k++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300487 elem = PyTuple_GET_ITEM(arg, k);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000488 Py_INCREF(elem);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300489 PyTuple_SET_ITEM(result, k, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 }
491 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300492 PyTuple_SET_ITEM(result, i, newelem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000493 }
494 if (result)
495 return result;
496 /* Fall through, returning arg. */
497 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300498 else if (PyList_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200499 Py_ssize_t i, size;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300500 PyObject *elem, *newelem, *result;
501
502 size = PyList_GET_SIZE(arg);
503 result = PyTuple_New(size);
504 if (!result)
505 return NULL;
506 /* Recursively invoke SplitObj for all list items. */
507 for(i = 0; i < size; i++) {
508 elem = PyList_GET_ITEM(arg, i);
509 newelem = SplitObj(elem);
510 if (!newelem) {
511 Py_XDECREF(result);
512 return NULL;
513 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300514 PyTuple_SET_ITEM(result, i, newelem);
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300515 }
516 return result;
517 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300518 else if (PyUnicode_Check(arg)) {
519 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300520 const char **argv;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200521 const char *list = PyUnicode_AsUTF8(arg);
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300522
523 if (list == NULL ||
524 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
525 Py_INCREF(arg);
526 return arg;
527 }
528 Tcl_Free(FREECAST argv);
529 if (argc > 1)
530 return Split(list);
531 /* Fall through, returning arg. */
532 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 else if (PyBytes_Check(arg)) {
534 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300535 const char **argv;
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300536 char *list = PyBytes_AS_STRING(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000537
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000538 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
539 Py_INCREF(arg);
540 return arg;
541 }
542 Tcl_Free(FREECAST argv);
543 if (argc > 1)
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300544 return Split(PyBytes_AS_STRING(arg));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000545 /* Fall through, returning arg. */
546 }
547 Py_INCREF(arg);
548 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000549}
Barry Warsawfa701a81997-01-16 00:15:11 +0000550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +0300552/*[clinic input]
553module _tkinter
554class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec"
555class _tkinter.Tcl_Obj "PyTclObject *" "&PyTclObject_Type_spec"
556class _tkinter.tktimertoken "TkttObject *" "&Tktt_Type_spec"
557[clinic start generated code]*/
558/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b1ebf15c162ee229]*/
559
Guido van Rossum18468821994-06-20 07:49:28 +0000560/**** Tkapp Object ****/
561
562#ifndef WITH_APPINIT
563int
Fred Drake509d79a2000-07-08 04:04:38 +0000564Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000565{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000566 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000567
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000568 if (Tcl_Init(interp) == TCL_ERROR) {
569 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
570 return TCL_ERROR;
571 }
Guilherme Polob681df42009-02-09 22:33:59 +0000572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000573 _tkinter_skip_tk_init = Tcl_GetVar(interp,
574 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
575 if (_tkinter_skip_tk_init != NULL &&
576 strcmp(_tkinter_skip_tk_init, "1") == 0) {
577 return TCL_OK;
578 }
Guilherme Polob681df42009-02-09 22:33:59 +0000579
580#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000581 if (tk_load_failed) {
582 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
583 return TCL_ERROR;
584 }
Guilherme Polob681df42009-02-09 22:33:59 +0000585#endif
586
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000587 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000588#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000589 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000590#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
592 return TCL_ERROR;
593 }
Guilherme Polob681df42009-02-09 22:33:59 +0000594
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000595 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000596}
597#endif /* !WITH_APPINIT */
598
Guido van Rossum18468821994-06-20 07:49:28 +0000599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000600
Barry Warsawfa701a81997-01-16 00:15:11 +0000601
602/* Initialize the Tk application; see the `main' function in
603 * `tkMain.c'.
604 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000605
Thomas Wouters58d05102000-07-24 14:43:35 +0000606static void EnableEventHook(void); /* Forward */
607static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000608
Barry Warsawfa701a81997-01-16 00:15:11 +0000609static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300610Tkapp_New(const char *screenName, const char *className,
611 int interactive, int wantobjects, int wantTk, int sync,
612 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000613{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 TkappObject *v;
615 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000616
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300617 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 if (v == NULL)
619 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200620 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000621
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000622 v->interp = Tcl_CreateInterp();
623 v->wantobjects = wantobjects;
624 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
625 TCL_GLOBAL_ONLY) != NULL;
626 v->thread_id = Tcl_GetCurrentThread();
627 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000628
629#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300631 PyErr_SetString(PyExc_RuntimeError,
632 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 Py_DECREF(v);
634 return 0;
635 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000636#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 if (v->threaded && tcl_lock) {
638 /* If Tcl is threaded, we don't need the lock. */
639 PyThread_free_lock(tcl_lock);
640 tcl_lock = NULL;
641 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000642
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200643 v->OldBooleanType = Tcl_GetObjType("boolean");
644 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 v->ByteArrayType = Tcl_GetObjType("bytearray");
646 v->DoubleType = Tcl_GetObjType("double");
647 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300648 v->WideIntType = Tcl_GetObjType("wideInt");
649 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 v->ListType = Tcl_GetObjType("list");
651 v->ProcBodyType = Tcl_GetObjType("procbody");
652 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 /* Delete the 'exit' command, which can screw things up */
655 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000656
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000657 if (screenName != NULL)
658 Tcl_SetVar2(v->interp, "env", "DISPLAY",
659 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 if (interactive)
662 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
663 else
664 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200667 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 if (!argv0) {
669 PyErr_NoMemory();
670 Py_DECREF(v);
671 return NULL;
672 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200675 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
676 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200678 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000679
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000680 if (! wantTk) {
681 Tcl_SetVar(v->interp,
682 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
683 }
Guilherme Polob681df42009-02-09 22:33:59 +0000684#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 else if (tk_load_failed) {
686 Tcl_SetVar(v->interp,
687 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
688 }
Guilherme Polob681df42009-02-09 22:33:59 +0000689#endif
David Aschere2b4b322004-02-18 05:59:53 +0000690
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 /* some initial arguments need to be in argv */
692 if (sync || use) {
693 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200694 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000696 if (sync)
697 len += sizeof "-sync";
698 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200699 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000700
Victor Stinneree6c3c72014-09-11 17:50:21 +0200701 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 if (!args) {
703 PyErr_NoMemory();
704 Py_DECREF(v);
705 return NULL;
706 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000707
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000708 args[0] = '\0';
709 if (sync)
710 strcat(args, "-sync");
711 if (use) {
712 if (sync)
713 strcat(args, " ");
714 strcat(args, "-use ");
715 strcat(args, use);
716 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200719 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000721
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500722#ifdef MS_WINDOWS
723 {
724 PyObject *str_path;
725 PyObject *utf8_path;
726 DWORD ret;
727
728 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
729 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
730 str_path = _get_tcl_lib_path();
731 if (str_path == NULL && PyErr_Occurred()) {
732 return NULL;
733 }
734 if (str_path != NULL) {
735 utf8_path = PyUnicode_AsUTF8String(str_path);
736 if (utf8_path == NULL) {
737 return NULL;
738 }
739 Tcl_SetVar(v->interp,
740 "tcl_library",
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300741 PyBytes_AS_STRING(utf8_path),
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500742 TCL_GLOBAL_ONLY);
743 Py_DECREF(utf8_path);
744 }
745 }
746 }
747#endif
748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 if (Tcl_AppInit(v->interp) != TCL_OK) {
750 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000751#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752 if (wantTk) {
753 const char *_tkinter_tk_failed;
754 _tkinter_tk_failed = Tcl_GetVar(v->interp,
755 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000756
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000757 if ( _tkinter_tk_failed != NULL &&
758 strcmp(_tkinter_tk_failed, "1") == 0) {
759 tk_load_failed = 1;
760 }
761 }
Guilherme Polob681df42009-02-09 22:33:59 +0000762#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000763 Py_DECREF((PyObject *)v);
764 return (TkappObject *)result;
765 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000766
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000767 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000770}
771
Barry Warsawfa701a81997-01-16 00:15:11 +0000772
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000773static void
774Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000776{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000777 Py_BEGIN_ALLOW_THREADS;
778 Tcl_MutexLock(mutex);
779 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
780 Tcl_ThreadAlert(self->thread_id);
781 Tcl_ConditionWait(cond, mutex, NULL);
782 Tcl_MutexUnlock(mutex);
783 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000784}
785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000786
Guido van Rossum18468821994-06-20 07:49:28 +0000787/** Tcl Eval **/
788
Martin v. Löwisffad6332002-11-26 09:28:05 +0000789typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000790 PyObject_HEAD
791 Tcl_Obj *value;
792 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000793} PyTclObject;
794
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300795static PyObject *PyTclObject_Type;
796#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000797
798static PyObject *
799newPyTclObject(Tcl_Obj *arg)
800{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000801 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300802 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000803 if (self == NULL)
804 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200805 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000806 Tcl_IncrRefCount(arg);
807 self->value = arg;
808 self->string = NULL;
809 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000810}
811
812static void
813PyTclObject_dealloc(PyTclObject *self)
814{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200815 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000816 Tcl_DecrRefCount(self->value);
817 Py_XDECREF(self->string);
818 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200819 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000820}
821
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200822static const char *
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000823PyTclObject_TclString(PyObject *self)
824{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000825 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000826}
827
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000828/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000829PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000830"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000831
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000832static PyObject *
833PyTclObject_string(PyTclObject *self, void *ignored)
834{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000835 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200836 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000837 if (!self->string)
838 return NULL;
839 }
840 Py_INCREF(self->string);
841 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000842}
843
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000844static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000845PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000846{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200847 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000848 Py_INCREF(self->string);
849 return self->string;
850 }
851 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200852 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000853}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000854
Martin v. Löwisffad6332002-11-26 09:28:05 +0000855static PyObject *
856PyTclObject_repr(PyTclObject *self)
857{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300858 PyObject *repr, *str = PyTclObject_str(self, NULL);
859 if (str == NULL)
860 return NULL;
861 repr = PyUnicode_FromFormat("<%s object: %R>",
862 self->value->typePtr->name, str);
863 Py_DECREF(str);
864 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000865}
866
Mark Dickinson211c6252009-02-01 10:28:51 +0000867#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
868
869static PyObject *
870PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000871{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000872 int result;
873 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000874
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000875 /* neither argument should be NULL, unless something's gone wrong */
876 if (self == NULL || other == NULL) {
877 PyErr_BadInternalCall();
878 return NULL;
879 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000880
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 /* both arguments should be instances of PyTclObject */
882 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
883 v = Py_NotImplemented;
884 goto finished;
885 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000886
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000887 if (self == other)
888 /* fast path when self and other are identical */
889 result = 0;
890 else
891 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
892 Tcl_GetString(((PyTclObject *)other)->value));
893 /* Convert return value to a Boolean */
894 switch (op) {
895 case Py_EQ:
896 v = TEST_COND(result == 0);
897 break;
898 case Py_NE:
899 v = TEST_COND(result != 0);
900 break;
901 case Py_LE:
902 v = TEST_COND(result <= 0);
903 break;
904 case Py_GE:
905 v = TEST_COND(result >= 0);
906 break;
907 case Py_LT:
908 v = TEST_COND(result < 0);
909 break;
910 case Py_GT:
911 v = TEST_COND(result > 0);
912 break;
913 default:
914 PyErr_BadArgument();
915 return NULL;
916 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000917 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000918 Py_INCREF(v);
919 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000920}
921
Martin v. Löwis39195712003-01-04 00:33:13 +0000922PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
923
Martin v. Löwisffad6332002-11-26 09:28:05 +0000924static PyObject*
925get_typename(PyTclObject* obj, void* ignored)
926{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200927 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000928}
929
Martin v. Löwis39195712003-01-04 00:33:13 +0000930
Martin v. Löwisffad6332002-11-26 09:28:05 +0000931static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000932 {"typename", (getter)get_typename, NULL, get_typename__doc__},
933 {"string", (getter)PyTclObject_string, NULL,
934 PyTclObject_string__doc__},
935 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000936};
937
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300938static PyType_Slot PyTclObject_Type_slots[] = {
939 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
940 {Py_tp_repr, (reprfunc)PyTclObject_repr},
941 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200942 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300943 {Py_tp_richcompare, PyTclObject_richcompare},
944 {Py_tp_getset, PyTclObject_getsetlist},
945 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000946};
947
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300948static PyType_Spec PyTclObject_Type_spec = {
949 "_tkinter.Tcl_Obj",
950 sizeof(PyTclObject),
951 0,
952 Py_TPFLAGS_DEFAULT,
953 PyTclObject_Type_slots,
954};
955
956
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700957#if SIZE_MAX > INT_MAX
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300958#define CHECK_STRING_LENGTH(s) do { \
959 if (s != NULL && strlen(s) >= INT_MAX) { \
960 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
961 return NULL; \
962 } } while(0)
963#else
964#define CHECK_STRING_LENGTH(s)
965#endif
966
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300967#ifdef HAVE_LIBTOMMAMTH
968static Tcl_Obj*
969asBignumObj(PyObject *value)
970{
971 Tcl_Obj *result;
972 int neg;
973 PyObject *hexstr;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200974 const char *hexchars;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300975 mp_int bigValue;
976
977 neg = Py_SIZE(value) < 0;
978 hexstr = _PyLong_Format(value, 16);
979 if (hexstr == NULL)
980 return NULL;
981 hexchars = PyUnicode_AsUTF8(hexstr);
982 if (hexchars == NULL) {
983 Py_DECREF(hexstr);
984 return NULL;
985 }
986 hexchars += neg + 2; /* skip sign and "0x" */
987 mp_init(&bigValue);
988 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
989 mp_clear(&bigValue);
990 Py_DECREF(hexstr);
991 PyErr_NoMemory();
992 return NULL;
993 }
994 Py_DECREF(hexstr);
995 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
996 result = Tcl_NewBignumObj(&bigValue);
997 mp_clear(&bigValue);
998 if (result == NULL) {
999 PyErr_NoMemory();
1000 return NULL;
1001 }
1002 return result;
1003}
1004#endif
1005
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001006static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001007AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001008{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001009 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001010
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001011 if (PyBytes_Check(value)) {
1012 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
1013 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1014 return NULL;
1015 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +03001016 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001017 (int)PyBytes_GET_SIZE(value));
1018 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001019
1020 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001021 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001022
1023 if (PyLong_CheckExact(value)) {
1024 int overflow;
1025 long longValue;
1026#ifdef TCL_WIDE_INT_TYPE
1027 Tcl_WideInt wideValue;
1028#endif
1029 longValue = PyLong_AsLongAndOverflow(value, &overflow);
1030 if (!overflow) {
1031 return Tcl_NewLongObj(longValue);
1032 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001033 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001034 fall through to wideInt handling. */
1035#ifdef TCL_WIDE_INT_TYPE
1036 if (_PyLong_AsByteArray((PyLongObject *)value,
1037 (unsigned char *)(void *)&wideValue,
1038 sizeof(wideValue),
1039 PY_LITTLE_ENDIAN,
1040 /* signed */ 1) == 0) {
1041 return Tcl_NewWideIntObj(wideValue);
1042 }
1043 PyErr_Clear();
1044#endif
1045 /* If there is an overflow in the wideInt conversion,
1046 fall through to bignum handling. */
1047#ifdef HAVE_LIBTOMMAMTH
1048 return asBignumObj(value);
1049#endif
1050 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001051 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001052 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001053
1054 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001056
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +03001057 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001058 Tcl_Obj **argv;
1059 Py_ssize_t size, i;
1060
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001061 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001062 if (size == 0)
1063 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001064 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001065 PyErr_SetString(PyExc_OverflowError,
1066 PyTuple_Check(value) ? "tuple is too long" :
1067 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001068 return NULL;
1069 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001070 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
1071 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001072 PyErr_NoMemory();
1073 return NULL;
1074 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001075 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001076 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001077 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001078 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001079 return result;
1080 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001081
1082 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001083 void *inbuf;
1084 Py_ssize_t size;
1085 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001086 Tcl_UniChar *outbuf = NULL;
1087 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001088 size_t allocsize;
1089
1090 if (PyUnicode_READY(value) == -1)
1091 return NULL;
1092
1093 inbuf = PyUnicode_DATA(value);
1094 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001095 if (size == 0)
1096 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001097 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1098 PyErr_SetString(PyExc_OverflowError, "string is too long");
1099 return NULL;
1100 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001101 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001102 if (kind == sizeof(Tcl_UniChar))
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001103 return Tcl_NewUnicodeObj(inbuf, (int)size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001104 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001105 outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001106 /* Else overflow occurred, and we take the next exit */
1107 if (!outbuf) {
1108 PyErr_NoMemory();
1109 return NULL;
1110 }
1111 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001112 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1113 /* We cannot test for sizeof(Tcl_UniChar) directly,
1114 so we test for UTF-8 size instead. */
1115#if TCL_UTF_MAX == 3
1116 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001117 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001118 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001119 "character U+%x is above the range "
1120 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001121 ch);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001122 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001123 return NULL;
1124 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001125#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001126 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001127 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001128 result = Tcl_NewUnicodeObj(outbuf, (int)size);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001129 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001130 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001131 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001132
1133 if (PyTclObject_Check(value)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001134 Tcl_Obj *v = ((PyTclObject*)value)->value;
1135 Tcl_IncrRefCount(v);
1136 return v;
1137 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001138
1139 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001140 PyObject *v = PyObject_Str(value);
1141 if (!v)
1142 return 0;
1143 result = AsObj(v);
1144 Py_DECREF(v);
1145 return result;
1146 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001147}
1148
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001149static PyObject *
1150fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1151{
1152 int boolValue;
1153 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1154 return Tkinter_Error(tkapp);
1155 return PyBool_FromLong(boolValue);
1156}
1157
Martin v. Löwisffad6332002-11-26 09:28:05 +00001158static PyObject*
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001159fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1160{
1161 Tcl_WideInt wideValue;
1162 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001163 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1164 return PyLong_FromLongLong(wideValue);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001165 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1166 sizeof(wideValue),
1167 PY_LITTLE_ENDIAN,
1168 /* signed */ 1);
1169 }
1170 return NULL;
1171}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001172
1173#ifdef HAVE_LIBTOMMAMTH
1174static PyObject*
1175fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1176{
1177 mp_int bigValue;
1178 unsigned long numBytes;
1179 unsigned char *bytes;
1180 PyObject *res;
1181
1182 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1183 return Tkinter_Error(tkapp);
1184 numBytes = mp_unsigned_bin_size(&bigValue);
1185 bytes = PyMem_Malloc(numBytes);
1186 if (bytes == NULL) {
1187 mp_clear(&bigValue);
1188 return PyErr_NoMemory();
1189 }
1190 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1191 &numBytes) != MP_OKAY) {
1192 mp_clear(&bigValue);
1193 PyMem_Free(bytes);
1194 return PyErr_NoMemory();
1195 }
1196 res = _PyLong_FromByteArray(bytes, numBytes,
1197 /* big-endian */ 0,
1198 /* unsigned */ 0);
1199 PyMem_Free(bytes);
1200 if (res != NULL && bigValue.sign == MP_NEG) {
1201 PyObject *res2 = PyNumber_Negative(res);
1202 Py_DECREF(res);
1203 res = res2;
1204 }
1205 mp_clear(&bigValue);
1206 return res;
1207}
1208#endif
1209
Martin v. Löwisffad6332002-11-26 09:28:05 +00001210static PyObject*
1211FromObj(PyObject* tkapp, Tcl_Obj *value)
1212{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001213 PyObject *result = NULL;
1214 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001215 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001216
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001217 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001218 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001219 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001220
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001221 if (value->typePtr == app->BooleanType ||
1222 value->typePtr == app->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001223 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001224 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001225
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001226 if (value->typePtr == app->ByteArrayType) {
1227 int size;
1228 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1229 return PyBytes_FromStringAndSize(data, size);
1230 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001231
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001232 if (value->typePtr == app->DoubleType) {
1233 return PyFloat_FromDouble(value->internalRep.doubleValue);
1234 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001236 if (value->typePtr == app->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001237 long longValue;
1238 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1239 return PyLong_FromLong(longValue);
1240 /* If there is an error in the long conversion,
1241 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001242 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001243
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001244 if (value->typePtr == app->IntType ||
1245 value->typePtr == app->WideIntType) {
1246 result = fromWideIntObj(tkapp, value);
1247 if (result != NULL || PyErr_Occurred())
1248 return result;
1249 Tcl_ResetResult(interp);
1250 /* If there is an error in the wideInt conversion,
1251 fall through to bignum handling. */
1252 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001253
1254#ifdef HAVE_LIBTOMMAMTH
1255 if (value->typePtr == app->IntType ||
1256 value->typePtr == app->WideIntType ||
1257 value->typePtr == app->BignumType) {
1258 return fromBignumObj(tkapp, value);
1259 }
1260#endif
1261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001262 if (value->typePtr == app->ListType) {
1263 int size;
1264 int i, status;
1265 PyObject *elem;
1266 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001267
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001268 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001269 if (status == TCL_ERROR)
1270 return Tkinter_Error(tkapp);
1271 result = PyTuple_New(size);
1272 if (!result)
1273 return NULL;
1274 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001275 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001276 if (status == TCL_ERROR) {
1277 Py_DECREF(result);
1278 return Tkinter_Error(tkapp);
1279 }
1280 elem = FromObj(tkapp, tcl_elem);
1281 if (!elem) {
1282 Py_DECREF(result);
1283 return NULL;
1284 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001285 PyTuple_SET_ITEM(result, i, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001286 }
1287 return result;
1288 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001289
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001290 if (value->typePtr == app->ProcBodyType) {
1291 /* fall through: return tcl object. */
1292 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001293
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001294 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001295 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001296 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001297 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001298 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001299
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001300#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001301 if (app->BooleanType == NULL &&
1302 strcmp(value->typePtr->name, "booleanString") == 0) {
1303 /* booleanString type is not registered in Tcl */
1304 app->BooleanType = value->typePtr;
1305 return fromBoolean(tkapp, value);
1306 }
1307#endif
1308
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001309#ifdef HAVE_LIBTOMMAMTH
1310 if (app->BignumType == NULL &&
1311 strcmp(value->typePtr->name, "bignum") == 0) {
1312 /* bignum type is not registered in Tcl */
1313 app->BignumType = value->typePtr;
1314 return fromBignumObj(tkapp, value);
1315 }
1316#endif
1317
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001318 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001319}
1320
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001321/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001322TCL_DECLARE_MUTEX(call_mutex)
1323
1324typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 Tcl_Event ev; /* Must be first */
1326 TkappObject *self;
1327 PyObject *args;
1328 int flags;
1329 PyObject **res;
1330 PyObject **exc_type, **exc_value, **exc_tb;
1331 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001332} Tkapp_CallEvent;
1333
1334void
1335Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001336{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001337 int i;
1338 for (i = 0; i < objc; i++)
1339 Tcl_DecrRefCount(objv[i]);
1340 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001341 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001342}
Guido van Rossum18468821994-06-20 07:49:28 +00001343
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001344/* Convert Python objects to Tcl objects. This must happen in the
1345 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001346
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001347static Tcl_Obj**
1348Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1349{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001351 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 if (args == NULL)
1353 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001354
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001355 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001356 objv[0] = AsObj(args);
Serhiy Storchaka0b3ec192017-03-23 17:53:47 +02001357 if (objv[0] == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001358 goto finally;
1359 objc = 1;
1360 Tcl_IncrRefCount(objv[0]);
1361 }
1362 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001363 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001364
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001365 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001366 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001367 PyErr_SetString(PyExc_OverflowError,
1368 PyTuple_Check(args) ? "tuple is too long" :
1369 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001370 return NULL;
1371 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001372 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001373 if (objv == NULL) {
1374 PyErr_NoMemory();
1375 objc = 0;
1376 goto finally;
1377 }
1378 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001380 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001381 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001382 if (v == Py_None) {
1383 objc = i;
1384 break;
1385 }
1386 objv[i] = AsObj(v);
1387 if (!objv[i]) {
1388 /* Reset objc, so it attempts to clear
1389 objects only up to i. */
1390 objc = i;
1391 goto finally;
1392 }
1393 Tcl_IncrRefCount(objv[i]);
1394 }
1395 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001396 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001397 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001398finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001399 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001400 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001401}
Guido van Rossum212643f1998-04-29 16:22:14 +00001402
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001403/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001404
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001405static PyObject*
1406Tkapp_CallResult(TkappObject *self)
1407{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001408 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001409 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001410 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001411 /* Not sure whether the IncrRef is necessary, but something
1412 may overwrite the interpreter result while we are
1413 converting it. */
1414 Tcl_IncrRefCount(value);
1415 res = FromObj((PyObject*)self, value);
1416 Tcl_DecrRefCount(value);
1417 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001418 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001419 }
1420 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001421}
Guido van Rossum632de272000-03-29 00:19:50 +00001422
Benjamin Peterson5879d412009-03-30 14:51:56 +00001423
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001424/* Tkapp_CallProc is the event procedure that is executed in the context of
1425 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1426 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001427
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001428static int
1429Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1430{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001431 Tcl_Obj *objStore[ARGSZ];
1432 Tcl_Obj **objv;
1433 int objc;
1434 int i;
1435 ENTER_PYTHON
1436 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1437 if (!objv) {
1438 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1439 *(e->res) = NULL;
1440 }
1441 LEAVE_PYTHON
1442 if (!objv)
1443 goto done;
1444 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1445 ENTER_PYTHON
1446 if (i == TCL_ERROR) {
1447 *(e->res) = NULL;
1448 *(e->exc_type) = NULL;
1449 *(e->exc_tb) = NULL;
1450 *(e->exc_value) = PyObject_CallFunction(
1451 Tkinter_TclError, "s",
1452 Tcl_GetStringResult(e->self->interp));
1453 }
1454 else {
1455 *(e->res) = Tkapp_CallResult(e->self);
1456 }
1457 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001459 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001460done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001461 /* Wake up calling thread. */
1462 Tcl_MutexLock(&call_mutex);
1463 Tcl_ConditionNotify(e->done);
1464 Tcl_MutexUnlock(&call_mutex);
1465 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001466}
1467
Benjamin Peterson5879d412009-03-30 14:51:56 +00001468
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001469/* This is the main entry point for calling a Tcl command.
1470 It supports three cases, with regard to threading:
1471 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1472 the context of the calling thread.
1473 2. Tcl is threaded, caller of the command is in the interpreter thread:
1474 Execute the command in the calling thread. Since the Tcl lock will
1475 not be used, we can merge that with case 1.
1476 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1477 the interpreter thread. Allocation of Tcl objects needs to occur in the
1478 interpreter thread, so we ship the PyObject* args to the target thread,
1479 and perform processing there. */
1480
1481static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001482Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001483{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 Tcl_Obj *objStore[ARGSZ];
1485 Tcl_Obj **objv = NULL;
1486 int objc, i;
1487 PyObject *res = NULL;
1488 TkappObject *self = (TkappObject*)selfptr;
1489 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001490
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001491 /* If args is a single tuple, replace with contents of tuple */
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001492 if (PyTuple_GET_SIZE(args) == 1) {
1493 PyObject *item = PyTuple_GET_ITEM(args, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001494 if (PyTuple_Check(item))
1495 args = item;
1496 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001497 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1498 /* We cannot call the command directly. Instead, we must
1499 marshal the parameters to the interpreter thread. */
1500 Tkapp_CallEvent *ev;
1501 Tcl_Condition cond = NULL;
1502 PyObject *exc_type, *exc_value, *exc_tb;
1503 if (!WaitForMainloop(self))
1504 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001505 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1506 if (ev == NULL) {
1507 PyErr_NoMemory();
1508 return NULL;
1509 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1511 ev->self = self;
1512 ev->args = args;
1513 ev->res = &res;
1514 ev->exc_type = &exc_type;
1515 ev->exc_value = &exc_value;
1516 ev->exc_tb = &exc_tb;
1517 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001518
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001519 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001520
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001521 if (res == NULL) {
1522 if (exc_type)
1523 PyErr_Restore(exc_type, exc_value, exc_tb);
1524 else
1525 PyErr_SetObject(Tkinter_TclError, exc_value);
1526 }
1527 Tcl_ConditionFinalize(&cond);
1528 }
1529 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001530 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001531
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001532 objv = Tkapp_CallArgs(args, objStore, &objc);
1533 if (!objv)
1534 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001535
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001536 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001537
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001538 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001539
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001540 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001541
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001542 if (i == TCL_ERROR)
1543 Tkinter_Error(selfptr);
1544 else
1545 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001546
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001548
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001549 Tkapp_CallDeallocArgs(objv, objStore, objc);
1550 }
1551 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001552}
1553
1554
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001555/*[clinic input]
1556_tkinter.tkapp.eval
1557
1558 script: str
1559 /
1560
1561[clinic start generated code]*/
1562
Barry Warsawfa701a81997-01-16 00:15:11 +00001563static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001564_tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1565/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001566{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001567 PyObject *res = NULL;
1568 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001569
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001570 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001571 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001573 ENTER_TCL
1574 err = Tcl_Eval(Tkapp_Interp(self), script);
1575 ENTER_OVERLAP
1576 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001577 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001578 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001579 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001580 LEAVE_OVERLAP_TCL
1581 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001582}
1583
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001584/*[clinic input]
1585_tkinter.tkapp.evalfile
1586
1587 fileName: str
1588 /
1589
1590[clinic start generated code]*/
1591
Guido van Rossum18468821994-06-20 07:49:28 +00001592static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001593_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1594/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001595{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001596 PyObject *res = NULL;
1597 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001598
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001599 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001600 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001602 ENTER_TCL
1603 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1604 ENTER_OVERLAP
1605 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001606 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001607 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001608 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001609 LEAVE_OVERLAP_TCL
1610 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001611}
1612
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001613/*[clinic input]
1614_tkinter.tkapp.record
1615
1616 script: str
1617 /
1618
1619[clinic start generated code]*/
1620
Guido van Rossum18468821994-06-20 07:49:28 +00001621static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001622_tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1623/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001624{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001625 PyObject *res = NULL;
1626 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001627
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001628 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001629 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001631 ENTER_TCL
1632 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1633 ENTER_OVERLAP
1634 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001635 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001636 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001637 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001638 LEAVE_OVERLAP_TCL
1639 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001640}
1641
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001642/*[clinic input]
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001643_tkinter.tkapp.adderrorinfo
Guido van Rossum18468821994-06-20 07:49:28 +00001644
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001645 msg: str
1646 /
1647
1648[clinic start generated code]*/
1649
1650static PyObject *
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03001651_tkinter_tkapp_adderrorinfo_impl(TkappObject *self, const char *msg)
1652/*[clinic end generated code: output=52162eaca2ee53cb input=f4b37aec7c7e8c77]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001653{
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001654 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001655 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001656
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001657 ENTER_TCL
1658 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1659 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001660
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001661 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001662}
1663
Barry Warsawfa701a81997-01-16 00:15:11 +00001664
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001665
Guido van Rossum18468821994-06-20 07:49:28 +00001666/** Tcl Variable **/
1667
Benjamin Peterson5879d412009-03-30 14:51:56 +00001668typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1669
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001670TCL_DECLARE_MUTEX(var_mutex)
1671
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001672typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001673 Tcl_Event ev; /* must be first */
1674 PyObject *self;
1675 PyObject *args;
1676 int flags;
1677 EventFunc func;
1678 PyObject **res;
1679 PyObject **exc_type;
1680 PyObject **exc_val;
1681 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001682} VarEvent;
1683
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001684/*[python]
1685
1686class varname_converter(CConverter):
1687 type = 'const char *'
1688 converter = 'varname_converter'
1689
1690[python]*/
1691/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1692
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001693static int
1694varname_converter(PyObject *in, void *_out)
1695{
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +02001696 const char *s;
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001697 const char **out = (const char**)_out;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001698 if (PyBytes_Check(in)) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001699 if (PyBytes_GET_SIZE(in) > INT_MAX) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001700 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1701 return 0;
1702 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001703 s = PyBytes_AS_STRING(in);
1704 if (strlen(s) != (size_t)PyBytes_GET_SIZE(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001705 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001706 return 0;
1707 }
1708 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001709 return 1;
1710 }
1711 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001712 Py_ssize_t size;
1713 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001714 if (s == NULL) {
1715 return 0;
1716 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001717 if (size > INT_MAX) {
1718 PyErr_SetString(PyExc_OverflowError, "string is too long");
1719 return 0;
1720 }
Victor Stinner706768c2014-08-16 01:03:39 +02001721 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001722 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001723 return 0;
1724 }
1725 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001726 return 1;
1727 }
1728 if (PyTclObject_Check(in)) {
1729 *out = PyTclObject_TclString(in);
1730 return 1;
1731 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001732 PyErr_Format(PyExc_TypeError,
1733 "must be str, bytes or Tcl_Obj, not %.50s",
1734 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001735 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001736}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001737
Benjamin Peterson5879d412009-03-30 14:51:56 +00001738
Martin v. Löwis59683e82008-06-13 07:50:45 +00001739static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001740var_perform(VarEvent *ev)
1741{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001742 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1743 if (!*(ev->res)) {
1744 PyObject *exc, *val, *tb;
1745 PyErr_Fetch(&exc, &val, &tb);
1746 PyErr_NormalizeException(&exc, &val, &tb);
1747 *(ev->exc_type) = exc;
1748 *(ev->exc_val) = val;
Serhiy Storchaka3ec5f422016-10-28 12:14:34 +03001749 Py_XDECREF(tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001750 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001751
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001752}
1753
1754static int
1755var_proc(VarEvent* ev, int flags)
1756{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001757 ENTER_PYTHON
1758 var_perform(ev);
1759 Tcl_MutexLock(&var_mutex);
1760 Tcl_ConditionNotify(ev->cond);
1761 Tcl_MutexUnlock(&var_mutex);
1762 LEAVE_PYTHON
1763 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001764}
1765
Benjamin Peterson5879d412009-03-30 14:51:56 +00001766
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001767static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001768var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001769{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001770 TkappObject *self = (TkappObject*)selfptr;
1771 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001772 VarEvent *ev;
1773 PyObject *res, *exc_type, *exc_val;
1774 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001775
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001776 /* The current thread is not the interpreter thread. Marshal
1777 the call to the interpreter thread, then wait for
1778 completion. */
1779 if (!WaitForMainloop(self))
1780 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001781
Serhiy Storchaka07940882014-09-11 10:38:54 +03001782 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1783 if (ev == NULL) {
1784 PyErr_NoMemory();
1785 return NULL;
1786 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001787 ev->self = selfptr;
1788 ev->args = args;
1789 ev->flags = flags;
1790 ev->func = func;
1791 ev->res = &res;
1792 ev->exc_type = &exc_type;
1793 ev->exc_val = &exc_val;
1794 ev->cond = &cond;
1795 ev->ev.proc = (Tcl_EventProc*)var_proc;
1796 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1797 Tcl_ConditionFinalize(&cond);
1798 if (!res) {
1799 PyErr_SetObject(exc_type, exc_val);
1800 Py_DECREF(exc_type);
1801 Py_DECREF(exc_val);
1802 return NULL;
1803 }
1804 return res;
1805 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001806 /* Tcl is not threaded, or this is the interpreter thread. */
1807 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001808}
1809
Guido van Rossum18468821994-06-20 07:49:28 +00001810static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001811SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001812{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001813 const char *name1, *name2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001814 PyObject *newValue;
1815 PyObject *res = NULL;
1816 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001817
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001818 switch (PyTuple_GET_SIZE(args)) {
1819 case 2:
1820 if (!PyArg_ParseTuple(args, "O&O:setvar",
1821 varname_converter, &name1, &newValue))
1822 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001823 /* XXX Acquire tcl lock??? */
1824 newval = AsObj(newValue);
1825 if (newval == NULL)
1826 return NULL;
1827 ENTER_TCL
1828 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1829 newval, flags);
1830 ENTER_OVERLAP
1831 if (!ok)
1832 Tkinter_Error(self);
1833 else {
1834 res = Py_None;
1835 Py_INCREF(res);
1836 }
1837 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001838 break;
1839 case 3:
1840 if (!PyArg_ParseTuple(args, "ssO:setvar",
1841 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001842 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001843 CHECK_STRING_LENGTH(name1);
1844 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001845 /* XXX must hold tcl lock already??? */
1846 newval = AsObj(newValue);
1847 ENTER_TCL
1848 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1849 ENTER_OVERLAP
1850 if (!ok)
1851 Tkinter_Error(self);
1852 else {
1853 res = Py_None;
1854 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001855 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001856 LEAVE_OVERLAP_TCL
1857 break;
1858 default:
1859 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1860 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001861 }
1862 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001863}
1864
1865static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001866Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001867{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001868 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001869}
1870
1871static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001872Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001873{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001874 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001875}
1876
Barry Warsawfa701a81997-01-16 00:15:11 +00001877
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001878
Guido van Rossum18468821994-06-20 07:49:28 +00001879static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001880GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001881{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001882 const char *name1, *name2=NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001883 PyObject *res = NULL;
1884 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001885
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001886 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1887 varname_converter, &name1, &name2))
1888 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001889
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001890 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001891 ENTER_TCL
1892 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1893 ENTER_OVERLAP
1894 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001895 PyErr_SetString(Tkinter_TclError,
1896 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001897 } else {
1898 if (((TkappObject*)self)->wantobjects) {
1899 res = FromObj(self, tres);
1900 }
1901 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001902 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001903 }
1904 }
1905 LEAVE_OVERLAP_TCL
1906 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001907}
1908
1909static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001910Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001911{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001912 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001913}
1914
1915static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001916Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001917{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001918 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001919}
1920
Barry Warsawfa701a81997-01-16 00:15:11 +00001921
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001922
Guido van Rossum18468821994-06-20 07:49:28 +00001923static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001924UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001925{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001926 char *name1, *name2=NULL;
1927 int code;
1928 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001929
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001930 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1931 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001932
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001933 CHECK_STRING_LENGTH(name1);
1934 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001935 ENTER_TCL
1936 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1937 ENTER_OVERLAP
1938 if (code == TCL_ERROR)
1939 res = Tkinter_Error(self);
1940 else {
1941 Py_INCREF(Py_None);
1942 res = Py_None;
1943 }
1944 LEAVE_OVERLAP_TCL
1945 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001946}
1947
1948static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001949Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001950{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001951 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001952}
1953
1954static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001955Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001956{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001957 return var_invoke(UnsetVar, self, args,
1958 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001959}
1960
Barry Warsawfa701a81997-01-16 00:15:11 +00001961
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001962
Guido van Rossum18468821994-06-20 07:49:28 +00001963/** Tcl to Python **/
1964
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001965/*[clinic input]
1966_tkinter.tkapp.getint
1967
1968 arg: object
1969 /
1970
1971[clinic start generated code]*/
1972
Guido van Rossum18468821994-06-20 07:49:28 +00001973static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001974_tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
1975/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001976{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001977 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001978 Tcl_Obj *value;
1979 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00001980
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001981 if (PyLong_Check(arg)) {
1982 Py_INCREF(arg);
1983 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001984 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001985
Serhiy Storchaka645058d2015-05-06 14:00:04 +03001986 if (PyTclObject_Check(arg)) {
1987 value = ((PyTclObject*)arg)->value;
1988 Tcl_IncrRefCount(value);
1989 }
1990 else {
1991 if (!PyArg_Parse(arg, "s:getint", &s))
1992 return NULL;
1993 CHECK_STRING_LENGTH(s);
1994 value = Tcl_NewStringObj(s, -1);
1995 if (value == NULL)
1996 return Tkinter_Error((PyObject *)self);
1997 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001998 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
1999 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
2000
2001 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
2002 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
2003 */
2004#ifdef HAVE_LIBTOMMAMTH
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002005 result = fromBignumObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002006#else
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002007 result = fromWideIntObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002008#endif
2009 Tcl_DecrRefCount(value);
2010 if (result != NULL || PyErr_Occurred())
2011 return result;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002012 return Tkinter_Error((PyObject *)self);
Guido van Rossum18468821994-06-20 07:49:28 +00002013}
2014
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002015/*[clinic input]
2016_tkinter.tkapp.getdouble
2017
2018 arg: object
2019 /
2020
2021[clinic start generated code]*/
2022
Guido van Rossum18468821994-06-20 07:49:28 +00002023static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002024_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
2025/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002026{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002027 char *s;
2028 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00002029
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002030 if (PyFloat_Check(arg)) {
2031 Py_INCREF(arg);
2032 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002033 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002034
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002035 if (PyNumber_Check(arg)) {
2036 return PyNumber_Float(arg);
2037 }
2038
2039 if (PyTclObject_Check(arg)) {
2040 if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
2041 ((PyTclObject*)arg)->value,
2042 &v) == TCL_ERROR)
2043 return Tkinter_Error((PyObject *)self);
2044 return PyFloat_FromDouble(v);
2045 }
2046
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002047 if (!PyArg_Parse(arg, "s:getdouble", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002048 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002049 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002050 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002051 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002052 return PyFloat_FromDouble(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002053}
2054
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002055/*[clinic input]
2056_tkinter.tkapp.getboolean
2057
2058 arg: object
2059 /
2060
2061[clinic start generated code]*/
2062
Guido van Rossum18468821994-06-20 07:49:28 +00002063static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002064_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
2065/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002066{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002067 char *s;
2068 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002069
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002070 if (PyLong_Check(arg)) { /* int or bool */
2071 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002072 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002073
2074 if (PyTclObject_Check(arg)) {
2075 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2076 ((PyTclObject*)arg)->value,
2077 &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002078 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002079 return PyBool_FromLong(v);
2080 }
2081
2082 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002083 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002084 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002085 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002086 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002087 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002088}
2089
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002090/*[clinic input]
2091_tkinter.tkapp.exprstring
2092
2093 s: str
2094 /
2095
2096[clinic start generated code]*/
2097
Guido van Rossum18468821994-06-20 07:49:28 +00002098static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002099_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2100/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002101{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002102 PyObject *res = NULL;
2103 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002104
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002105 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002106 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002107
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002108 ENTER_TCL
2109 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2110 ENTER_OVERLAP
2111 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002112 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002113 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002114 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115 LEAVE_OVERLAP_TCL
2116 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002117}
2118
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002119/*[clinic input]
2120_tkinter.tkapp.exprlong
2121
2122 s: str
2123 /
2124
2125[clinic start generated code]*/
2126
Guido van Rossum18468821994-06-20 07:49:28 +00002127static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002128_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2129/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002130{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002131 PyObject *res = NULL;
2132 int retval;
2133 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002134
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002135 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002136 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002137
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 ENTER_TCL
2139 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2140 ENTER_OVERLAP
2141 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002142 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002143 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002144 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002145 LEAVE_OVERLAP_TCL
2146 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002147}
2148
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002149/*[clinic input]
2150_tkinter.tkapp.exprdouble
2151
2152 s: str
2153 /
2154
2155[clinic start generated code]*/
2156
Guido van Rossum18468821994-06-20 07:49:28 +00002157static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002158_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2159/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002160{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002161 PyObject *res = NULL;
2162 double v;
2163 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002164
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002165 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002166 CHECK_TCL_APPARTMENT;
2167 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2168 ENTER_TCL
2169 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2170 ENTER_OVERLAP
2171 PyFPE_END_PROTECT(retval)
2172 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002173 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002174 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002175 res = PyFloat_FromDouble(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002176 LEAVE_OVERLAP_TCL
2177 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002178}
2179
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002180/*[clinic input]
2181_tkinter.tkapp.exprboolean
2182
2183 s: str
2184 /
2185
2186[clinic start generated code]*/
2187
Guido van Rossum18468821994-06-20 07:49:28 +00002188static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002189_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2190/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002191{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002192 PyObject *res = NULL;
2193 int retval;
2194 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002195
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002196 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 CHECK_TCL_APPARTMENT;
2198 ENTER_TCL
2199 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2200 ENTER_OVERLAP
2201 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002202 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002203 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002204 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002205 LEAVE_OVERLAP_TCL
2206 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002207}
2208
Barry Warsawfa701a81997-01-16 00:15:11 +00002209
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002210
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002211/*[clinic input]
2212_tkinter.tkapp.splitlist
2213
2214 arg: object
2215 /
2216
2217[clinic start generated code]*/
2218
Guido van Rossum18468821994-06-20 07:49:28 +00002219static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002220_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2221/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002222{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002223 char *list;
2224 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002225 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002226 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002227 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002228
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002229 if (PyTclObject_Check(arg)) {
2230 int objc;
2231 Tcl_Obj **objv;
2232 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2233 ((PyTclObject*)arg)->value,
2234 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002235 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002236 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002237 if (!(v = PyTuple_New(objc)))
2238 return NULL;
2239 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002240 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002241 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002242 Py_DECREF(v);
2243 return NULL;
2244 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002245 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002246 }
2247 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002248 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002249 if (PyTuple_Check(arg)) {
2250 Py_INCREF(arg);
2251 return arg;
2252 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002253 if (PyList_Check(arg)) {
2254 return PySequence_Tuple(arg);
2255 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002256
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002257 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002258 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002259
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002260 if (strlen(list) >= INT_MAX) {
2261 PyErr_SetString(PyExc_OverflowError, "string is too long");
2262 PyMem_Free(list);
2263 return NULL;
2264 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002265 if (Tcl_SplitList(Tkapp_Interp(self), list,
2266 &argc, &argv) == TCL_ERROR) {
2267 PyMem_Free(list);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002268 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002269 }
Guido van Rossum18468821994-06-20 07:49:28 +00002270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002271 if (!(v = PyTuple_New(argc)))
2272 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002273
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002274 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002275 PyObject *s = unicodeFromTclString(argv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002276 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002277 Py_DECREF(v);
2278 v = NULL;
2279 goto finally;
2280 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002281 PyTuple_SET_ITEM(v, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002282 }
Guido van Rossum18468821994-06-20 07:49:28 +00002283
Barry Warsawfa701a81997-01-16 00:15:11 +00002284 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002285 ckfree(FREECAST argv);
2286 PyMem_Free(list);
2287 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002288}
2289
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002290/*[clinic input]
2291_tkinter.tkapp.split
2292
2293 arg: object
2294 /
2295
2296[clinic start generated code]*/
2297
Guido van Rossum18468821994-06-20 07:49:28 +00002298static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002299_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2300/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002301{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002302 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002303 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002304
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002305 if (PyTclObject_Check(arg)) {
2306 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2307 int objc;
2308 Tcl_Obj **objv;
2309 int i;
2310 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2311 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002312 return FromObj((PyObject*)self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002313 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002314 if (objc == 0)
2315 return PyUnicode_FromString("");
2316 if (objc == 1)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002317 return FromObj((PyObject*)self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002318 if (!(v = PyTuple_New(objc)))
2319 return NULL;
2320 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002321 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002322 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002323 Py_DECREF(v);
2324 return NULL;
2325 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002326 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002327 }
2328 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002329 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002330 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002331 return SplitObj(arg);
2332
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002333 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002334 return NULL;
Serhiy Storchaka27c623c2017-10-03 22:39:55 +03002335 if (strlen(list) >= INT_MAX) {
2336 PyErr_SetString(PyExc_OverflowError, "string is too long");
2337 PyMem_Free(list);
2338 return NULL;
2339 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002340 v = Split(list);
2341 PyMem_Free(list);
2342 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002343}
2344
Barry Warsawfa701a81997-01-16 00:15:11 +00002345
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002346
Guido van Rossum18468821994-06-20 07:49:28 +00002347/** Tcl Command **/
2348
Guido van Rossum00d93061998-05-28 23:06:38 +00002349/* Client data struct */
2350typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002351 PyObject *self;
2352 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002353} PythonCmd_ClientData;
2354
2355static int
Fred Drake509d79a2000-07-08 04:04:38 +00002356PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002357{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002358 errorInCmd = 1;
2359 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2360 LEAVE_PYTHON
2361 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002362}
2363
Guido van Rossum18468821994-06-20 07:49:28 +00002364/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002365 * function or method.
2366 */
Guido van Rossum18468821994-06-20 07:49:28 +00002367static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002368PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002369{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002370 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002371 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002372 int i, rv;
2373 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002374
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002375 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002377 /* TBD: no error checking here since we know, via the
2378 * Tkapp_CreateCommand() that the client data is a two-tuple
2379 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002380 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002382 /* Create argument list (argv1, ..., argvN) */
2383 if (!(arg = PyTuple_New(argc - 1)))
2384 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002385
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002386 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002387 PyObject *s = unicodeFromTclString(argv[i + 1]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002388 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002389 Py_DECREF(arg);
2390 return PythonCmd_Error(interp);
2391 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002392 PyTuple_SET_ITEM(arg, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002393 }
INADA Naoki72dccde2017-02-16 09:26:01 +09002394 res = PyObject_Call(func, arg, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002395 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002397 if (res == NULL)
2398 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002399
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002400 obj_res = AsObj(res);
2401 if (obj_res == NULL) {
2402 Py_DECREF(res);
2403 return PythonCmd_Error(interp);
2404 }
2405 else {
2406 Tcl_SetObjResult(interp, obj_res);
2407 rv = TCL_OK;
2408 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002409
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002410 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002411
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002412 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002413
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002414 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002415}
2416
2417static void
Fred Drake509d79a2000-07-08 04:04:38 +00002418PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002419{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002420 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002421
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002422 ENTER_PYTHON
2423 Py_XDECREF(data->self);
2424 Py_XDECREF(data->func);
2425 PyMem_DEL(data);
2426 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002427}
2428
Barry Warsawfa701a81997-01-16 00:15:11 +00002429
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002430
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002431
2432TCL_DECLARE_MUTEX(command_mutex)
2433
2434typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002435 Tcl_Event ev;
2436 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002437 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002438 int create;
2439 int *status;
2440 ClientData *data;
2441 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002442} CommandEvent;
2443
2444static int
2445Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002446{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002447 if (ev->create)
2448 *ev->status = Tcl_CreateCommand(
2449 ev->interp, ev->name, PythonCmd,
2450 ev->data, PythonCmdDelete) == NULL;
2451 else
2452 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2453 Tcl_MutexLock(&command_mutex);
2454 Tcl_ConditionNotify(ev->done);
2455 Tcl_MutexUnlock(&command_mutex);
2456 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002457}
2458
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002459/*[clinic input]
2460_tkinter.tkapp.createcommand
2461
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002462 name: str
2463 func: object
2464 /
2465
2466[clinic start generated code]*/
2467
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002468static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002469_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2470 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002471/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002472{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002473 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002474 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002475
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002476 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 if (!PyCallable_Check(func)) {
2478 PyErr_SetString(PyExc_TypeError, "command not callable");
2479 return NULL;
2480 }
Guido van Rossum18468821994-06-20 07:49:28 +00002481
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002482 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2483 !WaitForMainloop(self))
2484 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002486 data = PyMem_NEW(PythonCmd_ClientData, 1);
2487 if (!data)
2488 return PyErr_NoMemory();
2489 Py_INCREF(self);
2490 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002491 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002492 data->func = func;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002493 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2494 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002495 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2496 if (ev == NULL) {
2497 PyErr_NoMemory();
2498 PyMem_DEL(data);
2499 return NULL;
2500 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002501 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2502 ev->interp = self->interp;
2503 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002504 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002505 ev->data = (ClientData)data;
2506 ev->status = &err;
2507 ev->done = &cond;
2508 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2509 Tcl_ConditionFinalize(&cond);
2510 }
2511 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002512 {
2513 ENTER_TCL
2514 err = Tcl_CreateCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002515 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002516 (ClientData)data, PythonCmdDelete) == NULL;
2517 LEAVE_TCL
2518 }
2519 if (err) {
2520 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2521 PyMem_DEL(data);
2522 return NULL;
2523 }
Guido van Rossum18468821994-06-20 07:49:28 +00002524
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002525 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002526}
2527
Barry Warsawfa701a81997-01-16 00:15:11 +00002528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002529
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002530/*[clinic input]
2531_tkinter.tkapp.deletecommand
2532
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002533 name: str
2534 /
2535
2536[clinic start generated code]*/
2537
Guido van Rossum18468821994-06-20 07:49:28 +00002538static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002539_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002540/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002541{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002542 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002543
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002544 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002546 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2547 Tcl_Condition cond = NULL;
2548 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002549 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2550 if (ev == NULL) {
2551 PyErr_NoMemory();
2552 return NULL;
2553 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002554 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2555 ev->interp = self->interp;
2556 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002557 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002558 ev->status = &err;
2559 ev->done = &cond;
2560 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2561 &command_mutex);
2562 Tcl_ConditionFinalize(&cond);
2563 }
2564 else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002565 {
2566 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002567 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002568 LEAVE_TCL
2569 }
2570 if (err == -1) {
2571 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2572 return NULL;
2573 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002574 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002575}
2576
Barry Warsawfa701a81997-01-16 00:15:11 +00002577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002578
Guido van Rossum00d93061998-05-28 23:06:38 +00002579#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002580/** File Handler **/
2581
Guido van Rossum00d93061998-05-28 23:06:38 +00002582typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002583 PyObject *func;
2584 PyObject *file;
2585 int id;
2586 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002587} FileHandler_ClientData;
2588
2589static FileHandler_ClientData *HeadFHCD;
2590
2591static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002592NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002593{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002594 FileHandler_ClientData *p;
2595 p = PyMem_NEW(FileHandler_ClientData, 1);
2596 if (p != NULL) {
2597 Py_XINCREF(func);
2598 Py_XINCREF(file);
2599 p->func = func;
2600 p->file = file;
2601 p->id = id;
2602 p->next = HeadFHCD;
2603 HeadFHCD = p;
2604 }
2605 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002606}
2607
2608static void
Fred Drake509d79a2000-07-08 04:04:38 +00002609DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002610{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002611 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002613 pp = &HeadFHCD;
2614 while ((p = *pp) != NULL) {
2615 if (p->id == id) {
2616 *pp = p->next;
2617 Py_XDECREF(p->func);
2618 Py_XDECREF(p->file);
2619 PyMem_DEL(p);
2620 }
2621 else
2622 pp = &p->next;
2623 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002624}
2625
Guido van Rossuma597dde1995-01-10 20:56:29 +00002626static void
Fred Drake509d79a2000-07-08 04:04:38 +00002627FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002628{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002629 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
INADA Naoki72dccde2017-02-16 09:26:01 +09002630 PyObject *func, *file, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002632 ENTER_PYTHON
2633 func = data->func;
2634 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002635
INADA Naoki72dccde2017-02-16 09:26:01 +09002636 res = PyObject_CallFunction(func, "Oi", file, mask);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002637 if (res == NULL) {
2638 errorInCmd = 1;
2639 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2640 }
2641 Py_XDECREF(res);
2642 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002643}
2644
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002645/*[clinic input]
2646_tkinter.tkapp.createfilehandler
2647
2648 file: object
2649 mask: int
2650 func: object
2651 /
2652
2653[clinic start generated code]*/
2654
Guido van Rossum18468821994-06-20 07:49:28 +00002655static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002656_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2657 int mask, PyObject *func)
2658/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002659{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002660 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002661 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002662
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002663 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002664
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002665 tfile = PyObject_AsFileDescriptor(file);
2666 if (tfile < 0)
2667 return NULL;
2668 if (!PyCallable_Check(func)) {
2669 PyErr_SetString(PyExc_TypeError, "bad argument list");
2670 return NULL;
2671 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002673 data = NewFHCD(func, file, tfile);
2674 if (data == NULL)
2675 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002676
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002677 /* Ought to check for null Tcl_File object... */
2678 ENTER_TCL
2679 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2680 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002681 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002682}
2683
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002684/*[clinic input]
2685_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002686
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002687 file: object
2688 /
2689
2690[clinic start generated code]*/
2691
2692static PyObject *
2693_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2694/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2695{
2696 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002697
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002698 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002700 tfile = PyObject_AsFileDescriptor(file);
2701 if (tfile < 0)
2702 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002703
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002704 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002705
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002706 /* Ought to check for null Tcl_File object... */
2707 ENTER_TCL
2708 Tcl_DeleteFileHandler(tfile);
2709 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002710 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002711}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002712#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002713
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002714
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002715/**** Tktt Object (timer token) ****/
2716
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002717static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002718
Guido van Rossum00d93061998-05-28 23:06:38 +00002719typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002720 PyObject_HEAD
2721 Tcl_TimerToken token;
2722 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002723} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002724
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002725/*[clinic input]
2726_tkinter.tktimertoken.deletetimerhandler
2727
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002728[clinic start generated code]*/
2729
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002730static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002731_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002732/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002733{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002734 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002735 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002736
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002737 if (v->token != NULL) {
2738 Tcl_DeleteTimerHandler(v->token);
2739 v->token = NULL;
2740 }
2741 if (func != NULL) {
2742 v->func = NULL;
2743 Py_DECREF(func);
2744 Py_DECREF(v); /* See Tktt_New() */
2745 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002746 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002747}
2748
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002749static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002750Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002751{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002752 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002753
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002754 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002755 if (v == NULL)
2756 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002757 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002758
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002759 Py_INCREF(func);
2760 v->token = NULL;
2761 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002762
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002763 /* Extra reference, deleted when called or when handler is deleted */
2764 Py_INCREF(v);
2765 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002766}
2767
2768static void
Fred Drake509d79a2000-07-08 04:04:38 +00002769Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002770{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002771 TkttObject *v = (TkttObject *)self;
2772 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002773 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002774
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002775 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002776
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002777 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002778 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002779}
2780
Guido van Rossum597ac201998-05-12 14:36:19 +00002781static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002782Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002783{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002784 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002785 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2786 v,
2787 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002788}
2789
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002790/** Timer Handler **/
2791
2792static void
Fred Drake509d79a2000-07-08 04:04:38 +00002793TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002794{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002795 TkttObject *v = (TkttObject *)clientData;
2796 PyObject *func = v->func;
2797 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002798
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002799 if (func == NULL)
2800 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002801
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002802 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002803
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002804 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002805
INADA Naoki72dccde2017-02-16 09:26:01 +09002806 res = _PyObject_CallNoArg(func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002807 Py_DECREF(func);
2808 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002809
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002810 if (res == NULL) {
2811 errorInCmd = 1;
2812 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2813 }
2814 else
2815 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002816
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002817 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002818}
2819
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002820/*[clinic input]
2821_tkinter.tkapp.createtimerhandler
2822
2823 milliseconds: int
2824 func: object
2825 /
2826
2827[clinic start generated code]*/
2828
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002829static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002830_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2831 PyObject *func)
2832/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002833{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002834 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002835
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002836 if (!PyCallable_Check(func)) {
2837 PyErr_SetString(PyExc_TypeError, "bad argument list");
2838 return NULL;
2839 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002840
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002841 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002842
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002843 v = Tktt_New(func);
2844 if (v) {
2845 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2846 (ClientData)v);
2847 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002848
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002849 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002850}
2851
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002852
Guido van Rossum18468821994-06-20 07:49:28 +00002853/** Event Loop **/
2854
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002855/*[clinic input]
2856_tkinter.tkapp.mainloop
2857
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002858 threshold: int = 0
2859 /
2860
2861[clinic start generated code]*/
2862
Guido van Rossum18468821994-06-20 07:49:28 +00002863static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002864_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002865/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002866{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002867 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002868
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002869 CHECK_TCL_APPARTMENT;
2870 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002871
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002872 quitMainLoop = 0;
2873 while (Tk_GetNumMainWindows() > threshold &&
2874 !quitMainLoop &&
2875 !errorInCmd)
2876 {
2877 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002878
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002879 if (self->threaded) {
2880 /* Allow other Python threads to run. */
2881 ENTER_TCL
2882 result = Tcl_DoOneEvent(0);
2883 LEAVE_TCL
2884 }
2885 else {
2886 Py_BEGIN_ALLOW_THREADS
2887 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2888 tcl_tstate = tstate;
2889 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2890 tcl_tstate = NULL;
2891 if(tcl_lock)PyThread_release_lock(tcl_lock);
2892 if (result == 0)
2893 Sleep(Tkinter_busywaitinterval);
2894 Py_END_ALLOW_THREADS
2895 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002896
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002897 if (PyErr_CheckSignals() != 0) {
2898 self->dispatching = 0;
2899 return NULL;
2900 }
2901 if (result < 0)
2902 break;
2903 }
2904 self->dispatching = 0;
2905 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002906
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002907 if (errorInCmd) {
2908 errorInCmd = 0;
2909 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2910 excInCmd = valInCmd = trbInCmd = NULL;
2911 return NULL;
2912 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002913 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002914}
2915
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002916/*[clinic input]
2917_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002918
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002919 flags: int = 0
2920 /
2921
2922[clinic start generated code]*/
2923
2924static PyObject *
2925_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2926/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2927{
2928 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002929
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002930 ENTER_TCL
2931 rv = Tcl_DoOneEvent(flags);
2932 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002933 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002934}
2935
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002936/*[clinic input]
2937_tkinter.tkapp.quit
2938[clinic start generated code]*/
2939
Guido van Rossum062cfb01995-01-10 17:42:51 +00002940static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002941_tkinter_tkapp_quit_impl(TkappObject *self)
2942/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002943{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002944 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002945 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002946}
2947
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002948/*[clinic input]
2949_tkinter.tkapp.interpaddr
2950[clinic start generated code]*/
2951
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002952static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002953_tkinter_tkapp_interpaddr_impl(TkappObject *self)
2954/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002955{
Victor Stinnere1040e22013-09-05 00:22:24 +02002956 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002957}
2958
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002959/*[clinic input]
2960_tkinter.tkapp.loadtk
2961[clinic start generated code]*/
2962
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002963static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002964_tkinter_tkapp_loadtk_impl(TkappObject *self)
2965/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00002966{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002967 Tcl_Interp *interp = Tkapp_Interp(self);
2968 const char * _tk_exists = NULL;
2969 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002970
Guilherme Polob681df42009-02-09 22:33:59 +00002971#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002972 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2973 * first call failed.
2974 * To avoid the deadlock, we just refuse the second call through
2975 * a static variable.
2976 */
2977 if (tk_load_failed) {
2978 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2979 return NULL;
2980 }
Guilherme Polob681df42009-02-09 22:33:59 +00002981#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002982
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002983 /* We want to guard against calling Tk_Init() multiple times */
2984 CHECK_TCL_APPARTMENT;
2985 ENTER_TCL
2986 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2987 ENTER_OVERLAP
2988 if (err == TCL_ERROR) {
2989 /* This sets an exception, but we cannot return right
2990 away because we need to exit the overlap first. */
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002991 Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002992 } else {
2993 _tk_exists = Tkapp_Result(self);
2994 }
2995 LEAVE_OVERLAP_TCL
2996 if (err == TCL_ERROR) {
2997 return NULL;
2998 }
2999 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
3000 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003001 PyErr_SetString(Tkinter_TclError,
3002 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00003003#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003004 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00003005#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003006 return NULL;
3007 }
3008 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003009 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00003010}
Barry Warsawfa701a81997-01-16 00:15:11 +00003011
Martin v. Löwisffad6332002-11-26 09:28:05 +00003012static PyObject *
3013Tkapp_WantObjects(PyObject *self, PyObject *args)
3014{
3015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003016 int wantobjects = -1;
3017 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3018 return NULL;
3019 if (wantobjects == -1)
3020 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3021 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003022
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003023 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003024}
3025
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003026/*[clinic input]
3027_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003028
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003029[clinic start generated code]*/
3030
3031static PyObject *
3032_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03003033/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003034{
3035 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003036
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003037 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003038}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003039
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003040
Guido van Rossum18468821994-06-20 07:49:28 +00003041/**** Tkapp Type Methods ****/
3042
3043static void
Fred Drake509d79a2000-07-08 04:04:38 +00003044Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003045{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003046 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003047 /*CHECK_TCL_APPARTMENT;*/
3048 ENTER_TCL
3049 Tcl_DeleteInterp(Tkapp_Interp(self));
3050 LEAVE_TCL
3051 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003052 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003053 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003054}
3055
Barry Warsawfa701a81997-01-16 00:15:11 +00003056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003057
Guido van Rossum18468821994-06-20 07:49:28 +00003058/**** Tkinter Module ****/
3059
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003060typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003061 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003062 Py_ssize_t size; /* current size */
3063 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003064} FlattenContext;
3065
3066static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003067_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003068{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003069 /* expand tuple to hold (at least) size new items.
3070 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003071
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003072 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003073
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003074 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003075 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003076
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003077 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003078
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003079 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003080}
3081
3082static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003083_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003084{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003085 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003086
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003087 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003088
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003089 if (depth > 1000) {
3090 PyErr_SetString(PyExc_ValueError,
3091 "nesting too deep in _flatten");
3092 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003093 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3094 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003095 /* preallocate (assume no nesting) */
3096 if (context->size + size > context->maxsize &&
3097 !_bump(context, size))
3098 return 0;
3099 /* copy items to output tuple */
3100 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003101 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003102 if (PyList_Check(o) || PyTuple_Check(o)) {
3103 if (!_flatten1(context, o, depth + 1))
3104 return 0;
3105 } else if (o != Py_None) {
3106 if (context->size + 1 > context->maxsize &&
3107 !_bump(context, 1))
3108 return 0;
3109 Py_INCREF(o);
3110 PyTuple_SET_ITEM(context->tuple,
3111 context->size++, o);
3112 }
3113 }
3114 } else {
3115 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3116 return 0;
3117 }
3118 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003119}
3120
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003121/*[clinic input]
3122_tkinter._flatten
3123
3124 item: object
3125 /
3126
3127[clinic start generated code]*/
3128
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003129static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003130_tkinter__flatten(PyObject *module, PyObject *item)
3131/*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003132{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003133 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003134
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003135 context.maxsize = PySequence_Size(item);
3136 if (context.maxsize < 0)
3137 return NULL;
3138 if (context.maxsize == 0)
3139 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003141 context.tuple = PyTuple_New(context.maxsize);
3142 if (!context.tuple)
3143 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003144
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003145 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003146
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003147 if (!_flatten1(&context, item,0))
3148 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003149
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003150 if (_PyTuple_Resize(&context.tuple, context.size))
3151 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003152
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003153 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003154}
3155
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003156/*[clinic input]
3157_tkinter.create
3158
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003159 screenName: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003160 baseName: str = NULL
3161 className: str = "Tk"
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003162 interactive: bool(accept={int}) = False
3163 wantobjects: bool(accept={int}) = False
3164 wantTk: bool(accept={int}) = True
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003165 if false, then Tk_Init() doesn't get called
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003166 sync: bool(accept={int}) = False
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003167 if true, then pass -sync to wish
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003168 use: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003169 if not None, then pass -use to wish
3170 /
3171
3172[clinic start generated code]*/
3173
Guido van Rossum18468821994-06-20 07:49:28 +00003174static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003175_tkinter_create_impl(PyObject *module, const char *screenName,
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003176 const char *baseName, const char *className,
3177 int interactive, int wantobjects, int wantTk, int sync,
3178 const char *use)
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003179/*[clinic end generated code: output=e3315607648e6bb4 input=431907c134c80085]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003180{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003181 /* XXX baseName is not used anymore;
3182 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003183 CHECK_STRING_LENGTH(screenName);
3184 CHECK_STRING_LENGTH(baseName);
3185 CHECK_STRING_LENGTH(className);
3186 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003187
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003188 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003189 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003190 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003191}
3192
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003193/*[clinic input]
3194_tkinter.setbusywaitinterval
3195
3196 new_val: int
3197 /
3198
3199Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3200
3201It should be set to a divisor of the maximum time between frames in an animation.
3202[clinic start generated code]*/
3203
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003204static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003205_tkinter_setbusywaitinterval_impl(PyObject *module, int new_val)
3206/*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003207{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003208 if (new_val < 0) {
3209 PyErr_SetString(PyExc_ValueError,
3210 "busywaitinterval must be >= 0");
3211 return NULL;
3212 }
3213 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003214 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003215}
3216
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003217/*[clinic input]
3218_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003219
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003220Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3221[clinic start generated code]*/
3222
3223static int
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003224_tkinter_getbusywaitinterval_impl(PyObject *module)
3225/*[clinic end generated code: output=23b72d552001f5c7 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003226{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003227 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003228}
3229
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003230#include "clinic/_tkinter.c.h"
3231
3232static PyMethodDef Tktt_methods[] =
3233{
3234 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3235 {NULL, NULL}
3236};
3237
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003238static PyType_Slot Tktt_Type_slots[] = {
3239 {Py_tp_dealloc, Tktt_Dealloc},
3240 {Py_tp_repr, Tktt_Repr},
3241 {Py_tp_methods, Tktt_methods},
3242 {0, 0}
3243};
3244
3245static PyType_Spec Tktt_Type_spec = {
3246 "_tkinter.tktimertoken",
3247 sizeof(TkttObject),
3248 0,
3249 Py_TPFLAGS_DEFAULT,
3250 Tktt_Type_slots,
3251};
3252
3253
3254/**** Tkapp Method List ****/
3255
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003256static PyMethodDef Tkapp_methods[] =
3257{
3258 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3259 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3260 {"call", Tkapp_Call, METH_VARARGS},
3261 _TKINTER_TKAPP_EVAL_METHODDEF
3262 _TKINTER_TKAPP_EVALFILE_METHODDEF
3263 _TKINTER_TKAPP_RECORD_METHODDEF
Serhiy Storchaka929b40a2017-10-03 21:37:22 +03003264 _TKINTER_TKAPP_ADDERRORINFO_METHODDEF
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003265 {"setvar", Tkapp_SetVar, METH_VARARGS},
3266 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3267 {"getvar", Tkapp_GetVar, METH_VARARGS},
3268 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3269 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3270 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3271 _TKINTER_TKAPP_GETINT_METHODDEF
3272 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3273 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3274 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3275 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3276 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3277 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3278 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3279 _TKINTER_TKAPP_SPLIT_METHODDEF
3280 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3281 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3282 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3283 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3284 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3285 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3286 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3287 _TKINTER_TKAPP_QUIT_METHODDEF
3288 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3289 _TKINTER_TKAPP_LOADTK_METHODDEF
3290 {NULL, NULL}
3291};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003292
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003293static PyType_Slot Tkapp_Type_slots[] = {
3294 {Py_tp_dealloc, Tkapp_Dealloc},
3295 {Py_tp_methods, Tkapp_methods},
3296 {0, 0}
3297};
3298
3299
3300static PyType_Spec Tkapp_Type_spec = {
3301 "_tkinter.tkapp",
3302 sizeof(TkappObject),
3303 0,
3304 Py_TPFLAGS_DEFAULT,
3305 Tkapp_Type_slots,
3306};
3307
Guido van Rossum18468821994-06-20 07:49:28 +00003308static PyMethodDef moduleMethods[] =
3309{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003310 _TKINTER__FLATTEN_METHODDEF
3311 _TKINTER_CREATE_METHODDEF
3312 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3313 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003314 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003315};
3316
Guido van Rossum7bf15641998-05-22 18:28:17 +00003317#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003318
3319static int stdin_ready = 0;
3320
Guido van Rossumad4db171998-06-13 13:56:28 +00003321#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003322static void
Fred Drake509d79a2000-07-08 04:04:38 +00003323MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003324{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003325 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003326}
Guido van Rossumad4db171998-06-13 13:56:28 +00003327#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003328
Guido van Rossum00d93061998-05-28 23:06:38 +00003329static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003330
Guido van Rossum18468821994-06-20 07:49:28 +00003331static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003332EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003333{
Guido van Rossumad4db171998-06-13 13:56:28 +00003334#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003335 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003336#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003337 PyEval_RestoreThread(event_tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003338 stdin_ready = 0;
3339 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003340#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003341 tfile = fileno(stdin);
3342 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003343#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003344 while (!errorInCmd && !stdin_ready) {
3345 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003346#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003347 if (_kbhit()) {
3348 stdin_ready = 1;
3349 break;
3350 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003351#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003352 Py_BEGIN_ALLOW_THREADS
3353 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3354 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003356 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003357
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003358 tcl_tstate = NULL;
3359 if(tcl_lock)PyThread_release_lock(tcl_lock);
3360 if (result == 0)
3361 Sleep(Tkinter_busywaitinterval);
3362 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003364 if (result < 0)
3365 break;
3366 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003367#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003368 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003369#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003370 if (errorInCmd) {
3371 errorInCmd = 0;
3372 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3373 excInCmd = valInCmd = trbInCmd = NULL;
3374 PyErr_Print();
3375 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003376 PyEval_SaveThread();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003377 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003378}
Guido van Rossum18468821994-06-20 07:49:28 +00003379
Guido van Rossum00d93061998-05-28 23:06:38 +00003380#endif
3381
Guido van Rossum7bf15641998-05-22 18:28:17 +00003382static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003383EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003384{
Guido van Rossum00d93061998-05-28 23:06:38 +00003385#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003386 if (PyOS_InputHook == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003387 event_tstate = PyThreadState_Get();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003388 PyOS_InputHook = EventHook;
3389 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003390#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003391}
3392
3393static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003394DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003395{
Guido van Rossum00d93061998-05-28 23:06:38 +00003396#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003397 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3398 PyOS_InputHook = NULL;
3399 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003400#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003401}
3402
Barry Warsawfa701a81997-01-16 00:15:11 +00003403
Martin v. Löwis1a214512008-06-11 05:26:20 +00003404static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003405 PyModuleDef_HEAD_INIT,
3406 "_tkinter",
3407 NULL,
3408 -1,
3409 moduleMethods,
3410 NULL,
3411 NULL,
3412 NULL,
3413 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003414};
3415
Mark Hammond62b1ab12002-07-23 06:31:15 +00003416PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003417PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003418{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003419 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003421 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003422 if (tcl_lock == NULL)
3423 return NULL;
Guido van Rossumae92f011996-08-21 19:03:36 +00003424
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003425 m = PyModule_Create(&_tkintermodule);
3426 if (m == NULL)
3427 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003428
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003429 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3430 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003431 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003432 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003433 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003434 Py_INCREF(o);
3435 if (PyModule_AddObject(m, "TclError", o)) {
3436 Py_DECREF(o);
3437 Py_DECREF(m);
3438 return NULL;
3439 }
3440 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003441
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003442 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3443 Py_DECREF(m);
3444 return NULL;
3445 }
3446 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3447 Py_DECREF(m);
3448 return NULL;
3449 }
3450 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3451 Py_DECREF(m);
3452 return NULL;
3453 }
3454 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3455 Py_DECREF(m);
3456 return NULL;
3457 }
3458 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3459 Py_DECREF(m);
3460 return NULL;
3461 }
3462 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3463 Py_DECREF(m);
3464 return NULL;
3465 }
3466 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3467 Py_DECREF(m);
3468 return NULL;
3469 }
3470 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3471 Py_DECREF(m);
3472 return NULL;
3473 }
3474 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3475 Py_DECREF(m);
3476 return NULL;
3477 }
3478 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3479 Py_DECREF(m);
3480 return NULL;
3481 }
3482 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3483 Py_DECREF(m);
3484 return NULL;
3485 }
3486
3487 o = PyType_FromSpec(&Tkapp_Type_spec);
3488 if (o == NULL) {
3489 Py_DECREF(m);
3490 return NULL;
3491 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003492 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003493 if (PyModule_AddObject(m, "TkappType", o)) {
3494 Py_DECREF(o);
3495 Py_DECREF(m);
3496 return NULL;
3497 }
3498 Tkapp_Type = o;
3499
3500 o = PyType_FromSpec(&Tktt_Type_spec);
3501 if (o == NULL) {
3502 Py_DECREF(m);
3503 return NULL;
3504 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003505 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003506 if (PyModule_AddObject(m, "TkttType", o)) {
3507 Py_DECREF(o);
3508 Py_DECREF(m);
3509 return NULL;
3510 }
3511 Tktt_Type = o;
3512
3513 o = PyType_FromSpec(&PyTclObject_Type_spec);
3514 if (o == NULL) {
3515 Py_DECREF(m);
3516 return NULL;
3517 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003518 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003519 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3520 Py_DECREF(o);
3521 Py_DECREF(m);
3522 return NULL;
3523 }
3524 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003525
3526#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003527 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3528 * start waking up. Note that Tcl_FindExecutable will do this, this
3529 * code must be above it! The original warning from
3530 * tkMacOSXAppInit.c is copied below.
3531 *
3532 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3533 * Tcl interpreter for now. It probably should work to do this
3534 * in the other order, but for now it doesn't seem to.
3535 *
3536 */
3537 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003538#endif
3539
3540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003541 /* This helps the dynamic loader; in Unicode aware Tcl versions
3542 it also helps Tcl find its encodings. */
3543 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3544 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003545 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003546 if (cexe) {
3547#ifdef MS_WINDOWS
3548 int set_var = 0;
3549 PyObject *str_path;
3550 wchar_t *wcs_path;
3551 DWORD ret;
3552
3553 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3554
3555 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3556 str_path = _get_tcl_lib_path();
3557 if (str_path == NULL && PyErr_Occurred()) {
3558 return NULL;
3559 }
3560 if (str_path != NULL) {
3561 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3562 if (wcs_path == NULL) {
3563 return NULL;
3564 }
3565 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3566 set_var = 1;
3567 }
3568 }
3569
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003570 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003571
3572 if (set_var) {
3573 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3574 PyMem_Free(wcs_path);
3575 }
3576#else
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003577 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003578#endif /* MS_WINDOWS */
3579 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003580 Py_XDECREF(cexe);
3581 Py_DECREF(uexe);
3582 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003583
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003584 if (PyErr_Occurred()) {
3585 Py_DECREF(m);
3586 return NULL;
3587 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003588
Guido van Rossum43ff8681998-07-14 18:02:13 +00003589#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003590 /* This was not a good idea; through <Destroy> bindings,
3591 Tcl_Finalize() may invoke Python code but at that point the
3592 interpreter and thread state have already been destroyed! */
3593 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003594#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003595 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003596}