blob: 768df81c1e19369a403fb31366ceeecd33c8c500 [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 Rossum00d93061998-05-28 23:06:38 +000029#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000030#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000031#endif
32
Guido van Rossum2a5119b1998-05-29 01:28:40 +000033#ifdef MS_WINDOWS
34#include <windows.h>
35#endif
36
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030037#define CHECK_SIZE(size, elemsize) \
Serhiy Storchaka26861b02015-02-16 20:52:17 +020038 ((size_t)(size) <= Py_MIN((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030039
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000040/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
41 it always; if Tcl is not threaded, the thread functions in
42 Tcl are empty. */
43#define TCL_THREADS
44
Jack Jansencb852442001-12-09 23:15:56 +000045#ifdef TK_FRAMEWORK
46#include <Tcl/tcl.h>
47#include <Tk/tk.h>
48#else
Guido van Rossum18468821994-06-20 07:49:28 +000049#include <tcl.h>
50#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000051#endif
Guido van Rossum18468821994-06-20 07:49:28 +000052
Guilherme Polo2d87e422009-04-10 22:19:09 +000053#include "tkinter.h"
54
Serhiy Storchaka71b49dd2015-04-22 10:59:32 +030055#if TK_HEX_VERSION < 0x08040200
Serhiy Storchaka6716d602014-07-30 19:19:21 +030056#error "Tk older than 8.4 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000057#endif
58
Serhiy Storchaka3af7a382015-04-22 10:53:08 +030059#if TK_HEX_VERSION >= 0x08050208 && TK_HEX_VERSION < 0x08060000 || \
60 TK_HEX_VERSION >= 0x08060200
Serhiy Storchakaea134da2015-04-02 18:46:50 +030061#define HAVE_LIBTOMMAMTH
62#include <tclTomMath.h>
63#endif
64
Jack Janseneddc1442003-11-20 01:44:59 +000065#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000066#define HAVE_CREATEFILEHANDLER
67#endif
68
Guido van Rossum00d93061998-05-28 23:06:38 +000069#ifdef HAVE_CREATEFILEHANDLER
70
Neal Norwitzd948a432006-01-08 01:08:55 +000071/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
72 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
73#ifndef TCL_UNIX_FD
74# ifdef TCL_WIN_SOCKET
75# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
76# else
77# define TCL_UNIX_FD 1
78# endif
79#endif
80
Guido van Rossum00d93061998-05-28 23:06:38 +000081/* Tcl_CreateFileHandler() changed several times; these macros deal with the
82 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
83 Unix, only because Jack added it back); when available on Windows, it only
84 applies to sockets. */
85
Guido van Rossum7bf15641998-05-22 18:28:17 +000086#ifdef MS_WINDOWS
87#define FHANDLETYPE TCL_WIN_SOCKET
88#else
89#define FHANDLETYPE TCL_UNIX_FD
90#endif
91
Guido van Rossum00d93061998-05-28 23:06:38 +000092/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
93 which uses this to handle Tcl events while the user is typing commands. */
94
95#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +000096#define WAIT_FOR_STDIN
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#endif /* HAVE_CREATEFILEHANDLER */
100
Guido van Rossumad4db171998-06-13 13:56:28 +0000101#ifdef MS_WINDOWS
102#include <conio.h>
103#define WAIT_FOR_STDIN
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500104
105static PyObject *
106_get_tcl_lib_path()
107{
108 static PyObject *tcl_library_path = NULL;
109 static int already_checked = 0;
110
111 if (already_checked == 0) {
112 PyObject *prefix;
113 struct stat stat_buf;
114 int stat_return_value;
115
116 prefix = PyUnicode_FromWideChar(Py_GetPrefix(), -1);
117 if (prefix == NULL) {
118 return NULL;
119 }
120
121 /* Check expected location for an installed Python first */
122 tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION);
123 if (tcl_library_path == NULL) {
124 return NULL;
125 }
126 tcl_library_path = PyUnicode_Concat(prefix, tcl_library_path);
127 if (tcl_library_path == NULL) {
128 return NULL;
129 }
130 stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
131 if (stat_return_value == -2) {
132 return NULL;
133 }
134 if (stat_return_value == -1) {
135 /* install location doesn't exist, reset errno and see if
136 we're a repository build */
137 errno = 0;
138#ifdef Py_TCLTK_DIR
139 tcl_library_path = PyUnicode_FromString(
140 Py_TCLTK_DIR "\\lib\\tcl" TCL_VERSION);
141 if (tcl_library_path == NULL) {
142 return NULL;
143 }
144 stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
145 if (stat_return_value == -2) {
146 return NULL;
147 }
148 if (stat_return_value == -1) {
149 /* tcltkDir for a repository build doesn't exist either,
150 reset errno and leave Tcl to its own devices */
151 errno = 0;
152 tcl_library_path = NULL;
153 }
154#else
155 tcl_library_path = NULL;
Guido van Rossumad4db171998-06-13 13:56:28 +0000156#endif
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500157 }
158 already_checked = 1;
159 }
160 return tcl_library_path;
161}
162#endif /* MS_WINDOWS */
Guido van Rossumad4db171998-06-13 13:56:28 +0000163
Guido van Rossum00d93061998-05-28 23:06:38 +0000164#ifdef WITH_THREAD
165
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000166/* The threading situation is complicated. Tcl is not thread-safe, except
167 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000168
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300169 So we need to use a lock around all uses of Tcl. Previously, the
170 Python interpreter lock was used for this. However, this causes
171 problems when other Python threads need to run while Tcl is blocked
172 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000173
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300174 To solve this problem, a separate lock for Tcl is introduced.
175 Holding it is incompatible with holding Python's interpreter lock.
176 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000177
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300178 ENTER_TCL and LEAVE_TCL are brackets, just like
179 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
180 used whenever a call into Tcl is made that could call an event
181 handler, or otherwise affect the state of a Tcl interpreter. These
182 assume that the surrounding code has the Python interpreter lock;
183 inside the brackets, the Python interpreter lock has been released
184 and the lock for Tcl has been acquired.
185
186 Sometimes, it is necessary to have both the Python lock and the Tcl
187 lock. (For example, when transferring data from the Tcl
188 interpreter result to a Python string object.) This can be done by
189 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
190 reacquires the Python lock (and restores the thread state) but
191 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
192 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000193
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000194 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300195 handlers when the handler needs to use Python. Such event handlers
196 are entered while the lock for Tcl is held; the event handler
197 presumably needs to use Python. ENTER_PYTHON releases the lock for
198 Tcl and acquires the Python interpreter lock, restoring the
199 appropriate thread state, and LEAVE_PYTHON releases the Python
200 interpreter lock and re-acquires the lock for Tcl. It is okay for
201 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
202 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000203
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300204 These locks expand to several statements and brackets; they should
205 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000206
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300207 If Tcl is threaded, this approach won't work anymore. The Tcl
208 interpreter is only valid in the thread that created it, and all Tk
209 activity must happen in this thread, also. That means that the
210 mainloop must be invoked in the thread that created the
211 interpreter. Invoking commands from other threads is possible;
212 _tkinter will queue an event for the interpreter thread, which will
213 then execute the command and pass back the result. If the main
214 thread is not in the mainloop, and invoking commands causes an
215 exception; if the main loop is running but not processing events,
216 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000217
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300218 In addition, for a threaded Tcl, a single global tcl_tstate won't
219 be sufficient anymore, since multiple Tcl interpreters may
220 simultaneously dispatch in different threads. So we use the Tcl TLS
221 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000222
Guido van Rossum00d93061998-05-28 23:06:38 +0000223*/
224
Guido van Rossum65d5b571998-12-21 19:32:43 +0000225static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000226
227#ifdef TCL_THREADS
228static Tcl_ThreadDataKey state_key;
229typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300230#define tcl_tstate \
231 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000232#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000233static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000234#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000235
236#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000237 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
238 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000239
240#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300241 tcl_tstate = NULL; \
242 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000243
Guido van Rossum62320c91998-06-15 04:36:09 +0000244#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000245 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000246
247#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000248 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000249
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000250#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000251 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300252 if(tcl_lock) \
253 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000254
255#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000256 { PyThreadState *tstate = PyEval_SaveThread(); \
257 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000258
259#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 if (((TkappObject *)self)->threaded && \
261 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300262 PyErr_SetString(PyExc_RuntimeError, \
263 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000264 return 0; \
265 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000266
267#else
268
269#define ENTER_TCL
270#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000271#define ENTER_OVERLAP
272#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000273#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000274#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000275#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000276
277#endif
278
Guido van Rossum97867b21996-08-08 19:09:53 +0000279#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000280#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000281#endif
282
Guido van Rossum18468821994-06-20 07:49:28 +0000283/**** Tkapp Object Declaration ****/
284
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300285static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000286
Guido van Rossum00d93061998-05-28 23:06:38 +0000287typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000288 PyObject_HEAD
289 Tcl_Interp *interp;
290 int wantobjects;
291 int threaded; /* True if tcl_platform[threaded] */
292 Tcl_ThreadId thread_id;
293 int dispatching;
294 /* We cannot include tclInt.h, as this is internal.
295 So we cache interesting types here. */
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200296 const Tcl_ObjType *OldBooleanType;
Zachary Ware037605b2014-08-05 11:54:34 -0500297 const Tcl_ObjType *BooleanType;
298 const Tcl_ObjType *ByteArrayType;
299 const Tcl_ObjType *DoubleType;
300 const Tcl_ObjType *IntType;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300301 const Tcl_ObjType *WideIntType;
302 const Tcl_ObjType *BignumType;
Zachary Ware037605b2014-08-05 11:54:34 -0500303 const Tcl_ObjType *ListType;
304 const Tcl_ObjType *ProcBodyType;
305 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000306} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000307
Guido van Rossum18468821994-06-20 07:49:28 +0000308#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000309#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000310
Guido van Rossum35d43371997-08-02 00:09:09 +0000311#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000312(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000313
Barry Warsawfa701a81997-01-16 00:15:11 +0000314
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000315
Guido van Rossum18468821994-06-20 07:49:28 +0000316/**** Error Handling ****/
317
318static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000319static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000320static int errorInCmd = 0;
321static PyObject *excInCmd;
322static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000323static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000324
Guilherme Polob681df42009-02-09 22:33:59 +0000325#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000326static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000327#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000328
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000329
Guido van Rossum18468821994-06-20 07:49:28 +0000330static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000331Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000332{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000333 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
334 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000335}
336
Barry Warsawfa701a81997-01-16 00:15:11 +0000337
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000338
Guido van Rossum18468821994-06-20 07:49:28 +0000339/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000340
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000341static int Tkinter_busywaitinterval = 20;
342
Guido van Rossum00d93061998-05-28 23:06:38 +0000343#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000344#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000345
Guido van Rossum00d93061998-05-28 23:06:38 +0000346/* Millisecond sleep() for Unix platforms. */
347
348static void
Fred Drake509d79a2000-07-08 04:04:38 +0000349Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000350{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000351 /* XXX Too bad if you don't have select(). */
352 struct timeval t;
353 t.tv_sec = milli/1000;
354 t.tv_usec = (milli%1000) * 1000;
355 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000356}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000357#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000358
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000359/* Wait up to 1s for the mainloop to come up. */
360
361static int
362WaitForMainloop(TkappObject* self)
363{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000364 int i;
365 for (i = 0; i < 10; i++) {
366 if (self->dispatching)
367 return 1;
368 Py_BEGIN_ALLOW_THREADS
369 Sleep(100);
370 Py_END_ALLOW_THREADS
371 }
372 if (self->dispatching)
373 return 1;
374 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
375 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000376}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000377#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000378
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000380
Guido van Rossum18468821994-06-20 07:49:28 +0000381#define ARGSZ 64
382
Barry Warsawfa701a81997-01-16 00:15:11 +0000383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000384
Guido van Rossum18468821994-06-20 07:49:28 +0000385static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200386unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
387{
388 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
389 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
390 /* Tcl encodes null character as \xc0\x80 */
391 if (memchr(s, '\xc0', size)) {
392 char *buf, *q;
393 const char *e = s + size;
394 PyErr_Clear();
395 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300396 if (buf == NULL) {
397 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200398 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300399 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200400 while (s != e) {
401 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
402 *q++ = '\0';
403 s += 2;
404 }
405 else
406 *q++ = *s++;
407 }
408 s = buf;
409 size = q - s;
410 r = PyUnicode_DecodeUTF8(s, size, NULL);
411 PyMem_Free(buf);
412 }
413 }
414 return r;
415}
416
417static PyObject *
418unicodeFromTclString(const char *s)
419{
420 return unicodeFromTclStringAndSize(s, strlen(s));
421}
422
423static PyObject *
424unicodeFromTclObj(Tcl_Obj *value)
425{
426 int len;
427 char *s = Tcl_GetStringFromObj(value, &len);
428 return unicodeFromTclStringAndSize(s, len);
429}
430
431
432static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300433Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000434{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000435 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300436 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000437 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000438
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000439 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300440 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000441 }
Guido van Rossum18468821994-06-20 07:49:28 +0000442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000443 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
444 /* Not a list.
445 * Could be a quoted string containing funnies, e.g. {"}.
446 * Return the string itself.
447 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200448 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000449 }
Guido van Rossum18468821994-06-20 07:49:28 +0000450
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000451 if (argc == 0)
452 v = PyUnicode_FromString("");
453 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200454 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000455 else if ((v = PyTuple_New(argc)) != NULL) {
456 int i;
457 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000459 for (i = 0; i < argc; i++) {
460 if ((w = Split(argv[i])) == NULL) {
461 Py_DECREF(v);
462 v = NULL;
463 break;
464 }
465 PyTuple_SetItem(v, i, w);
466 }
467 }
468 Tcl_Free(FREECAST argv);
469 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000470}
471
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300472/* In some cases, Tcl will still return strings that are supposed to
473 be lists. SplitObj walks through a nested tuple, finding string
474 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000475
Martin v. Löwis59683e82008-06-13 07:50:45 +0000476static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000477SplitObj(PyObject *arg)
478{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000479 if (PyTuple_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200480 Py_ssize_t i, size;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000481 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000483 size = PyTuple_Size(arg);
484 result = NULL;
485 /* Recursively invoke SplitObj for all tuple items.
486 If this does not return a new object, no action is
487 needed. */
488 for(i = 0; i < size; i++) {
489 elem = PyTuple_GetItem(arg, i);
490 newelem = SplitObj(elem);
491 if (!newelem) {
492 Py_XDECREF(result);
493 return NULL;
494 }
495 if (!result) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200496 Py_ssize_t k;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000497 if (newelem == elem) {
498 Py_DECREF(newelem);
499 continue;
500 }
501 result = PyTuple_New(size);
502 if (!result)
503 return NULL;
504 for(k = 0; k < i; k++) {
505 elem = PyTuple_GetItem(arg, k);
506 Py_INCREF(elem);
507 PyTuple_SetItem(result, k, elem);
508 }
509 }
510 PyTuple_SetItem(result, i, newelem);
511 }
512 if (result)
513 return result;
514 /* Fall through, returning arg. */
515 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300516 else if (PyList_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200517 Py_ssize_t i, size;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300518 PyObject *elem, *newelem, *result;
519
520 size = PyList_GET_SIZE(arg);
521 result = PyTuple_New(size);
522 if (!result)
523 return NULL;
524 /* Recursively invoke SplitObj for all list items. */
525 for(i = 0; i < size; i++) {
526 elem = PyList_GET_ITEM(arg, i);
527 newelem = SplitObj(elem);
528 if (!newelem) {
529 Py_XDECREF(result);
530 return NULL;
531 }
532 PyTuple_SetItem(result, i, newelem);
533 }
534 return result;
535 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300536 else if (PyUnicode_Check(arg)) {
537 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300538 const char **argv;
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300539 char *list = PyUnicode_AsUTF8(arg);
540
541 if (list == NULL ||
542 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
543 Py_INCREF(arg);
544 return arg;
545 }
546 Tcl_Free(FREECAST argv);
547 if (argc > 1)
548 return Split(list);
549 /* Fall through, returning arg. */
550 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551 else if (PyBytes_Check(arg)) {
552 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300553 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000555
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000556 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
557 Py_INCREF(arg);
558 return arg;
559 }
560 Tcl_Free(FREECAST argv);
561 if (argc > 1)
562 return Split(PyBytes_AsString(arg));
563 /* Fall through, returning arg. */
564 }
565 Py_INCREF(arg);
566 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000567}
Barry Warsawfa701a81997-01-16 00:15:11 +0000568
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000569
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +0300570/*[clinic input]
571module _tkinter
572class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec"
573class _tkinter.Tcl_Obj "PyTclObject *" "&PyTclObject_Type_spec"
574class _tkinter.tktimertoken "TkttObject *" "&Tktt_Type_spec"
575[clinic start generated code]*/
576/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b1ebf15c162ee229]*/
577
Guido van Rossum18468821994-06-20 07:49:28 +0000578/**** Tkapp Object ****/
579
580#ifndef WITH_APPINIT
581int
Fred Drake509d79a2000-07-08 04:04:38 +0000582Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000583{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000584 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000585
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 if (Tcl_Init(interp) == TCL_ERROR) {
587 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
588 return TCL_ERROR;
589 }
Guilherme Polob681df42009-02-09 22:33:59 +0000590
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 _tkinter_skip_tk_init = Tcl_GetVar(interp,
592 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
593 if (_tkinter_skip_tk_init != NULL &&
594 strcmp(_tkinter_skip_tk_init, "1") == 0) {
595 return TCL_OK;
596 }
Guilherme Polob681df42009-02-09 22:33:59 +0000597
598#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000599 if (tk_load_failed) {
600 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
601 return TCL_ERROR;
602 }
Guilherme Polob681df42009-02-09 22:33:59 +0000603#endif
604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000605 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000606#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000608#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
610 return TCL_ERROR;
611 }
Guilherme Polob681df42009-02-09 22:33:59 +0000612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000613 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000614}
615#endif /* !WITH_APPINIT */
616
Guido van Rossum18468821994-06-20 07:49:28 +0000617
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618
Barry Warsawfa701a81997-01-16 00:15:11 +0000619
620/* Initialize the Tk application; see the `main' function in
621 * `tkMain.c'.
622 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000623
Thomas Wouters58d05102000-07-24 14:43:35 +0000624static void EnableEventHook(void); /* Forward */
625static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000626
Barry Warsawfa701a81997-01-16 00:15:11 +0000627static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300628Tkapp_New(const char *screenName, const char *className,
629 int interactive, int wantobjects, int wantTk, int sync,
630 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000631{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 TkappObject *v;
633 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000634
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300635 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 if (v == NULL)
637 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200638 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000639
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000640 v->interp = Tcl_CreateInterp();
641 v->wantobjects = wantobjects;
642 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
643 TCL_GLOBAL_ONLY) != NULL;
644 v->thread_id = Tcl_GetCurrentThread();
645 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000646
647#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300649 PyErr_SetString(PyExc_RuntimeError,
650 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000651 Py_DECREF(v);
652 return 0;
653 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000654#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000655#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000656 if (v->threaded && tcl_lock) {
657 /* If Tcl is threaded, we don't need the lock. */
658 PyThread_free_lock(tcl_lock);
659 tcl_lock = NULL;
660 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000661#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000662
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200663 v->OldBooleanType = Tcl_GetObjType("boolean");
664 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000665 v->ByteArrayType = Tcl_GetObjType("bytearray");
666 v->DoubleType = Tcl_GetObjType("double");
667 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300668 v->WideIntType = Tcl_GetObjType("wideInt");
669 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000670 v->ListType = Tcl_GetObjType("list");
671 v->ProcBodyType = Tcl_GetObjType("procbody");
672 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 /* Delete the 'exit' command, which can screw things up */
675 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000676
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 if (screenName != NULL)
678 Tcl_SetVar2(v->interp, "env", "DISPLAY",
679 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000680
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000681 if (interactive)
682 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
683 else
684 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000685
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000686 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200687 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000688 if (!argv0) {
689 PyErr_NoMemory();
690 Py_DECREF(v);
691 return NULL;
692 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200695 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
696 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000697 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200698 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000700 if (! wantTk) {
701 Tcl_SetVar(v->interp,
702 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
703 }
Guilherme Polob681df42009-02-09 22:33:59 +0000704#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000705 else if (tk_load_failed) {
706 Tcl_SetVar(v->interp,
707 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
708 }
Guilherme Polob681df42009-02-09 22:33:59 +0000709#endif
David Aschere2b4b322004-02-18 05:59:53 +0000710
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000711 /* some initial arguments need to be in argv */
712 if (sync || use) {
713 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200714 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000715
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000716 if (sync)
717 len += sizeof "-sync";
718 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200719 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000720
Victor Stinneree6c3c72014-09-11 17:50:21 +0200721 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000722 if (!args) {
723 PyErr_NoMemory();
724 Py_DECREF(v);
725 return NULL;
726 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000727
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000728 args[0] = '\0';
729 if (sync)
730 strcat(args, "-sync");
731 if (use) {
732 if (sync)
733 strcat(args, " ");
734 strcat(args, "-use ");
735 strcat(args, use);
736 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000737
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000738 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200739 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000740 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000741
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500742#ifdef MS_WINDOWS
743 {
744 PyObject *str_path;
745 PyObject *utf8_path;
746 DWORD ret;
747
748 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
749 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
750 str_path = _get_tcl_lib_path();
751 if (str_path == NULL && PyErr_Occurred()) {
752 return NULL;
753 }
754 if (str_path != NULL) {
755 utf8_path = PyUnicode_AsUTF8String(str_path);
756 if (utf8_path == NULL) {
757 return NULL;
758 }
759 Tcl_SetVar(v->interp,
760 "tcl_library",
761 PyBytes_AsString(utf8_path),
762 TCL_GLOBAL_ONLY);
763 Py_DECREF(utf8_path);
764 }
765 }
766 }
767#endif
768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 if (Tcl_AppInit(v->interp) != TCL_OK) {
770 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000771#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000772 if (wantTk) {
773 const char *_tkinter_tk_failed;
774 _tkinter_tk_failed = Tcl_GetVar(v->interp,
775 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000776
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000777 if ( _tkinter_tk_failed != NULL &&
778 strcmp(_tkinter_tk_failed, "1") == 0) {
779 tk_load_failed = 1;
780 }
781 }
Guilherme Polob681df42009-02-09 22:33:59 +0000782#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000783 Py_DECREF((PyObject *)v);
784 return (TkappObject *)result;
785 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000786
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000787 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000788
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000789 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000790}
791
Barry Warsawfa701a81997-01-16 00:15:11 +0000792
Benjamin Peterson5879d412009-03-30 14:51:56 +0000793#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000794static void
795Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000796 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000797{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000798 Py_BEGIN_ALLOW_THREADS;
799 Tcl_MutexLock(mutex);
800 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
801 Tcl_ThreadAlert(self->thread_id);
802 Tcl_ConditionWait(cond, mutex, NULL);
803 Tcl_MutexUnlock(mutex);
804 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000805}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000806#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000807
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000808
Guido van Rossum18468821994-06-20 07:49:28 +0000809/** Tcl Eval **/
810
Martin v. Löwisffad6332002-11-26 09:28:05 +0000811typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000812 PyObject_HEAD
813 Tcl_Obj *value;
814 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000815} PyTclObject;
816
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300817static PyObject *PyTclObject_Type;
818#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000819
820static PyObject *
821newPyTclObject(Tcl_Obj *arg)
822{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000823 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300824 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000825 if (self == NULL)
826 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200827 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000828 Tcl_IncrRefCount(arg);
829 self->value = arg;
830 self->string = NULL;
831 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000832}
833
834static void
835PyTclObject_dealloc(PyTclObject *self)
836{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200837 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000838 Tcl_DecrRefCount(self->value);
839 Py_XDECREF(self->string);
840 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200841 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000842}
843
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200844static const char *
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000845PyTclObject_TclString(PyObject *self)
846{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000847 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000848}
849
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000850/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000851PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000852"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000853
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000854static PyObject *
855PyTclObject_string(PyTclObject *self, void *ignored)
856{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000857 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200858 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000859 if (!self->string)
860 return NULL;
861 }
862 Py_INCREF(self->string);
863 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000864}
865
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000866static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000867PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000868{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200869 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000870 Py_INCREF(self->string);
871 return self->string;
872 }
873 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200874 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000875}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000876
Martin v. Löwisffad6332002-11-26 09:28:05 +0000877static PyObject *
878PyTclObject_repr(PyTclObject *self)
879{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300880 PyObject *repr, *str = PyTclObject_str(self, NULL);
881 if (str == NULL)
882 return NULL;
883 repr = PyUnicode_FromFormat("<%s object: %R>",
884 self->value->typePtr->name, str);
885 Py_DECREF(str);
886 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000887}
888
Mark Dickinson211c6252009-02-01 10:28:51 +0000889#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
890
891static PyObject *
892PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000893{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000894 int result;
895 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000896
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000897 /* neither argument should be NULL, unless something's gone wrong */
898 if (self == NULL || other == NULL) {
899 PyErr_BadInternalCall();
900 return NULL;
901 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000902
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000903 /* both arguments should be instances of PyTclObject */
904 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
905 v = Py_NotImplemented;
906 goto finished;
907 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000908
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000909 if (self == other)
910 /* fast path when self and other are identical */
911 result = 0;
912 else
913 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
914 Tcl_GetString(((PyTclObject *)other)->value));
915 /* Convert return value to a Boolean */
916 switch (op) {
917 case Py_EQ:
918 v = TEST_COND(result == 0);
919 break;
920 case Py_NE:
921 v = TEST_COND(result != 0);
922 break;
923 case Py_LE:
924 v = TEST_COND(result <= 0);
925 break;
926 case Py_GE:
927 v = TEST_COND(result >= 0);
928 break;
929 case Py_LT:
930 v = TEST_COND(result < 0);
931 break;
932 case Py_GT:
933 v = TEST_COND(result > 0);
934 break;
935 default:
936 PyErr_BadArgument();
937 return NULL;
938 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000939 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000940 Py_INCREF(v);
941 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000942}
943
Martin v. Löwis39195712003-01-04 00:33:13 +0000944PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
945
Martin v. Löwisffad6332002-11-26 09:28:05 +0000946static PyObject*
947get_typename(PyTclObject* obj, void* ignored)
948{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200949 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000950}
951
Martin v. Löwis39195712003-01-04 00:33:13 +0000952
Martin v. Löwisffad6332002-11-26 09:28:05 +0000953static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000954 {"typename", (getter)get_typename, NULL, get_typename__doc__},
955 {"string", (getter)PyTclObject_string, NULL,
956 PyTclObject_string__doc__},
957 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000958};
959
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300960static PyType_Slot PyTclObject_Type_slots[] = {
961 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
962 {Py_tp_repr, (reprfunc)PyTclObject_repr},
963 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200964 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300965 {Py_tp_richcompare, PyTclObject_richcompare},
966 {Py_tp_getset, PyTclObject_getsetlist},
967 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000968};
969
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300970static PyType_Spec PyTclObject_Type_spec = {
971 "_tkinter.Tcl_Obj",
972 sizeof(PyTclObject),
973 0,
974 Py_TPFLAGS_DEFAULT,
975 PyTclObject_Type_slots,
976};
977
978
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300979#if PY_SIZE_MAX > INT_MAX
980#define CHECK_STRING_LENGTH(s) do { \
981 if (s != NULL && strlen(s) >= INT_MAX) { \
982 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
983 return NULL; \
984 } } while(0)
985#else
986#define CHECK_STRING_LENGTH(s)
987#endif
988
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300989#ifdef HAVE_LIBTOMMAMTH
990static Tcl_Obj*
991asBignumObj(PyObject *value)
992{
993 Tcl_Obj *result;
994 int neg;
995 PyObject *hexstr;
996 char *hexchars;
997 mp_int bigValue;
998
999 neg = Py_SIZE(value) < 0;
1000 hexstr = _PyLong_Format(value, 16);
1001 if (hexstr == NULL)
1002 return NULL;
1003 hexchars = PyUnicode_AsUTF8(hexstr);
1004 if (hexchars == NULL) {
1005 Py_DECREF(hexstr);
1006 return NULL;
1007 }
1008 hexchars += neg + 2; /* skip sign and "0x" */
1009 mp_init(&bigValue);
1010 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
1011 mp_clear(&bigValue);
1012 Py_DECREF(hexstr);
1013 PyErr_NoMemory();
1014 return NULL;
1015 }
1016 Py_DECREF(hexstr);
1017 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
1018 result = Tcl_NewBignumObj(&bigValue);
1019 mp_clear(&bigValue);
1020 if (result == NULL) {
1021 PyErr_NoMemory();
1022 return NULL;
1023 }
1024 return result;
1025}
1026#endif
1027
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001028static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001029AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001030{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001031 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001032
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001033 if (PyBytes_Check(value)) {
1034 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
1035 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1036 return NULL;
1037 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +03001038 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001039 (int)PyBytes_GET_SIZE(value));
1040 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001041
1042 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001043 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001044
1045 if (PyLong_CheckExact(value)) {
1046 int overflow;
1047 long longValue;
1048#ifdef TCL_WIDE_INT_TYPE
1049 Tcl_WideInt wideValue;
1050#endif
1051 longValue = PyLong_AsLongAndOverflow(value, &overflow);
1052 if (!overflow) {
1053 return Tcl_NewLongObj(longValue);
1054 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001056 fall through to wideInt handling. */
1057#ifdef TCL_WIDE_INT_TYPE
1058 if (_PyLong_AsByteArray((PyLongObject *)value,
1059 (unsigned char *)(void *)&wideValue,
1060 sizeof(wideValue),
1061 PY_LITTLE_ENDIAN,
1062 /* signed */ 1) == 0) {
1063 return Tcl_NewWideIntObj(wideValue);
1064 }
1065 PyErr_Clear();
1066#endif
1067 /* If there is an overflow in the wideInt conversion,
1068 fall through to bignum handling. */
1069#ifdef HAVE_LIBTOMMAMTH
1070 return asBignumObj(value);
1071#endif
1072 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001073 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001074 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001075
1076 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001077 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001078
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +03001079 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001080 Tcl_Obj **argv;
1081 Py_ssize_t size, i;
1082
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001083 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001084 if (size == 0)
1085 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001086 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001087 PyErr_SetString(PyExc_OverflowError,
1088 PyTuple_Check(value) ? "tuple is too long" :
1089 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001090 return NULL;
1091 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001092 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
1093 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001094 PyErr_NoMemory();
1095 return NULL;
1096 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001097 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001098 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001099 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001100 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001101 return result;
1102 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001103
1104 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001105 void *inbuf;
1106 Py_ssize_t size;
1107 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001108 Tcl_UniChar *outbuf = NULL;
1109 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001110 size_t allocsize;
1111
1112 if (PyUnicode_READY(value) == -1)
1113 return NULL;
1114
1115 inbuf = PyUnicode_DATA(value);
1116 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001117 if (size == 0)
1118 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001119 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1120 PyErr_SetString(PyExc_OverflowError, "string is too long");
1121 return NULL;
1122 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001123 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001124 if (kind == sizeof(Tcl_UniChar))
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001125 return Tcl_NewUnicodeObj(inbuf, (int)size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001126 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001127 outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001128 /* Else overflow occurred, and we take the next exit */
1129 if (!outbuf) {
1130 PyErr_NoMemory();
1131 return NULL;
1132 }
1133 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001134 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1135 /* We cannot test for sizeof(Tcl_UniChar) directly,
1136 so we test for UTF-8 size instead. */
1137#if TCL_UTF_MAX == 3
1138 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001139 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001140 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001141 "character U+%x is above the range "
1142 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001143 ch);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001144 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001145 return NULL;
1146 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001147#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001148 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001149 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001150 result = Tcl_NewUnicodeObj(outbuf, (int)size);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001151 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001152 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001153 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001154
1155 if (PyTclObject_Check(value)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001156 Tcl_Obj *v = ((PyTclObject*)value)->value;
1157 Tcl_IncrRefCount(v);
1158 return v;
1159 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001160
1161 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001162 PyObject *v = PyObject_Str(value);
1163 if (!v)
1164 return 0;
1165 result = AsObj(v);
1166 Py_DECREF(v);
1167 return result;
1168 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001169}
1170
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001171static PyObject *
1172fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1173{
1174 int boolValue;
1175 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1176 return Tkinter_Error(tkapp);
1177 return PyBool_FromLong(boolValue);
1178}
1179
Martin v. Löwisffad6332002-11-26 09:28:05 +00001180static PyObject*
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001181fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1182{
1183 Tcl_WideInt wideValue;
1184 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
1185#ifdef HAVE_LONG_LONG
1186 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1187 return PyLong_FromLongLong(wideValue);
1188#endif
1189 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1190 sizeof(wideValue),
1191 PY_LITTLE_ENDIAN,
1192 /* signed */ 1);
1193 }
1194 return NULL;
1195}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001196
1197#ifdef HAVE_LIBTOMMAMTH
1198static PyObject*
1199fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1200{
1201 mp_int bigValue;
1202 unsigned long numBytes;
1203 unsigned char *bytes;
1204 PyObject *res;
1205
1206 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1207 return Tkinter_Error(tkapp);
1208 numBytes = mp_unsigned_bin_size(&bigValue);
1209 bytes = PyMem_Malloc(numBytes);
1210 if (bytes == NULL) {
1211 mp_clear(&bigValue);
1212 return PyErr_NoMemory();
1213 }
1214 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1215 &numBytes) != MP_OKAY) {
1216 mp_clear(&bigValue);
1217 PyMem_Free(bytes);
1218 return PyErr_NoMemory();
1219 }
1220 res = _PyLong_FromByteArray(bytes, numBytes,
1221 /* big-endian */ 0,
1222 /* unsigned */ 0);
1223 PyMem_Free(bytes);
1224 if (res != NULL && bigValue.sign == MP_NEG) {
1225 PyObject *res2 = PyNumber_Negative(res);
1226 Py_DECREF(res);
1227 res = res2;
1228 }
1229 mp_clear(&bigValue);
1230 return res;
1231}
1232#endif
1233
Martin v. Löwisffad6332002-11-26 09:28:05 +00001234static PyObject*
1235FromObj(PyObject* tkapp, Tcl_Obj *value)
1236{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001237 PyObject *result = NULL;
1238 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001239 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001240
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001241 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001242 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001243 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001244
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001245 if (value->typePtr == app->BooleanType ||
1246 value->typePtr == app->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001247 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001248 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001249
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001250 if (value->typePtr == app->ByteArrayType) {
1251 int size;
1252 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1253 return PyBytes_FromStringAndSize(data, size);
1254 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001255
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001256 if (value->typePtr == app->DoubleType) {
1257 return PyFloat_FromDouble(value->internalRep.doubleValue);
1258 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001260 if (value->typePtr == app->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001261 long longValue;
1262 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1263 return PyLong_FromLong(longValue);
1264 /* If there is an error in the long conversion,
1265 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001266 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001267
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001268 if (value->typePtr == app->IntType ||
1269 value->typePtr == app->WideIntType) {
1270 result = fromWideIntObj(tkapp, value);
1271 if (result != NULL || PyErr_Occurred())
1272 return result;
1273 Tcl_ResetResult(interp);
1274 /* If there is an error in the wideInt conversion,
1275 fall through to bignum handling. */
1276 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001277
1278#ifdef HAVE_LIBTOMMAMTH
1279 if (value->typePtr == app->IntType ||
1280 value->typePtr == app->WideIntType ||
1281 value->typePtr == app->BignumType) {
1282 return fromBignumObj(tkapp, value);
1283 }
1284#endif
1285
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001286 if (value->typePtr == app->ListType) {
1287 int size;
1288 int i, status;
1289 PyObject *elem;
1290 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001291
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001292 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001293 if (status == TCL_ERROR)
1294 return Tkinter_Error(tkapp);
1295 result = PyTuple_New(size);
1296 if (!result)
1297 return NULL;
1298 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001299 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001300 if (status == TCL_ERROR) {
1301 Py_DECREF(result);
1302 return Tkinter_Error(tkapp);
1303 }
1304 elem = FromObj(tkapp, tcl_elem);
1305 if (!elem) {
1306 Py_DECREF(result);
1307 return NULL;
1308 }
1309 PyTuple_SetItem(result, i, elem);
1310 }
1311 return result;
1312 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001314 if (value->typePtr == app->ProcBodyType) {
1315 /* fall through: return tcl object. */
1316 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001317
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001318 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001319 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001320 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001321 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001322 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001323
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001324#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001325 if (app->BooleanType == NULL &&
1326 strcmp(value->typePtr->name, "booleanString") == 0) {
1327 /* booleanString type is not registered in Tcl */
1328 app->BooleanType = value->typePtr;
1329 return fromBoolean(tkapp, value);
1330 }
1331#endif
1332
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001333#ifdef HAVE_LIBTOMMAMTH
1334 if (app->BignumType == NULL &&
1335 strcmp(value->typePtr->name, "bignum") == 0) {
1336 /* bignum type is not registered in Tcl */
1337 app->BignumType = value->typePtr;
1338 return fromBignumObj(tkapp, value);
1339 }
1340#endif
1341
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001342 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001343}
1344
Benjamin Peterson5879d412009-03-30 14:51:56 +00001345#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001346/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001347TCL_DECLARE_MUTEX(call_mutex)
1348
1349typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 Tcl_Event ev; /* Must be first */
1351 TkappObject *self;
1352 PyObject *args;
1353 int flags;
1354 PyObject **res;
1355 PyObject **exc_type, **exc_value, **exc_tb;
1356 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001357} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001358#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001359
1360void
1361Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001362{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001363 int i;
1364 for (i = 0; i < objc; i++)
1365 Tcl_DecrRefCount(objv[i]);
1366 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001367 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001368}
Guido van Rossum18468821994-06-20 07:49:28 +00001369
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001370/* Convert Python objects to Tcl objects. This must happen in the
1371 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001372
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001373static Tcl_Obj**
1374Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1375{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001376 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001377 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001378 if (args == NULL)
1379 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001380
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001381 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001382 objv[0] = AsObj(args);
1383 if (objv[0] == 0)
1384 goto finally;
1385 objc = 1;
1386 Tcl_IncrRefCount(objv[0]);
1387 }
1388 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001389 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001391 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001392 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001393 PyErr_SetString(PyExc_OverflowError,
1394 PyTuple_Check(args) ? "tuple is too long" :
1395 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001396 return NULL;
1397 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001398 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001399 if (objv == NULL) {
1400 PyErr_NoMemory();
1401 objc = 0;
1402 goto finally;
1403 }
1404 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001405
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001406 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001407 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001408 if (v == Py_None) {
1409 objc = i;
1410 break;
1411 }
1412 objv[i] = AsObj(v);
1413 if (!objv[i]) {
1414 /* Reset objc, so it attempts to clear
1415 objects only up to i. */
1416 objc = i;
1417 goto finally;
1418 }
1419 Tcl_IncrRefCount(objv[i]);
1420 }
1421 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001422 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001423 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001424finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001425 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001426 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001427}
Guido van Rossum212643f1998-04-29 16:22:14 +00001428
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001429/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001430
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001431static PyObject*
1432Tkapp_CallResult(TkappObject *self)
1433{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001434 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001435 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001436 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001437 /* Not sure whether the IncrRef is necessary, but something
1438 may overwrite the interpreter result while we are
1439 converting it. */
1440 Tcl_IncrRefCount(value);
1441 res = FromObj((PyObject*)self, value);
1442 Tcl_DecrRefCount(value);
1443 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001444 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001445 }
1446 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001447}
Guido van Rossum632de272000-03-29 00:19:50 +00001448
Benjamin Peterson5879d412009-03-30 14:51:56 +00001449#ifdef WITH_THREAD
1450
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001451/* Tkapp_CallProc is the event procedure that is executed in the context of
1452 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1453 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001454
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001455static int
1456Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1457{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001458 Tcl_Obj *objStore[ARGSZ];
1459 Tcl_Obj **objv;
1460 int objc;
1461 int i;
1462 ENTER_PYTHON
1463 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1464 if (!objv) {
1465 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1466 *(e->res) = NULL;
1467 }
1468 LEAVE_PYTHON
1469 if (!objv)
1470 goto done;
1471 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1472 ENTER_PYTHON
1473 if (i == TCL_ERROR) {
1474 *(e->res) = NULL;
1475 *(e->exc_type) = NULL;
1476 *(e->exc_tb) = NULL;
1477 *(e->exc_value) = PyObject_CallFunction(
1478 Tkinter_TclError, "s",
1479 Tcl_GetStringResult(e->self->interp));
1480 }
1481 else {
1482 *(e->res) = Tkapp_CallResult(e->self);
1483 }
1484 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001486 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001487done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001488 /* Wake up calling thread. */
1489 Tcl_MutexLock(&call_mutex);
1490 Tcl_ConditionNotify(e->done);
1491 Tcl_MutexUnlock(&call_mutex);
1492 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001493}
1494
Benjamin Peterson5879d412009-03-30 14:51:56 +00001495#endif
1496
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001497/* This is the main entry point for calling a Tcl command.
1498 It supports three cases, with regard to threading:
1499 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1500 the context of the calling thread.
1501 2. Tcl is threaded, caller of the command is in the interpreter thread:
1502 Execute the command in the calling thread. Since the Tcl lock will
1503 not be used, we can merge that with case 1.
1504 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1505 the interpreter thread. Allocation of Tcl objects needs to occur in the
1506 interpreter thread, so we ship the PyObject* args to the target thread,
1507 and perform processing there. */
1508
1509static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001510Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001511{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001512 Tcl_Obj *objStore[ARGSZ];
1513 Tcl_Obj **objv = NULL;
1514 int objc, i;
1515 PyObject *res = NULL;
1516 TkappObject *self = (TkappObject*)selfptr;
1517 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001518
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001519 /* If args is a single tuple, replace with contents of tuple */
1520 if (1 == PyTuple_Size(args)){
1521 PyObject* item = PyTuple_GetItem(args, 0);
1522 if (PyTuple_Check(item))
1523 args = item;
1524 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001525#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001526 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1527 /* We cannot call the command directly. Instead, we must
1528 marshal the parameters to the interpreter thread. */
1529 Tkapp_CallEvent *ev;
1530 Tcl_Condition cond = NULL;
1531 PyObject *exc_type, *exc_value, *exc_tb;
1532 if (!WaitForMainloop(self))
1533 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001534 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1535 if (ev == NULL) {
1536 PyErr_NoMemory();
1537 return NULL;
1538 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001539 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1540 ev->self = self;
1541 ev->args = args;
1542 ev->res = &res;
1543 ev->exc_type = &exc_type;
1544 ev->exc_value = &exc_value;
1545 ev->exc_tb = &exc_tb;
1546 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001548 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001549
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 if (res == NULL) {
1551 if (exc_type)
1552 PyErr_Restore(exc_type, exc_value, exc_tb);
1553 else
1554 PyErr_SetObject(Tkinter_TclError, exc_value);
1555 }
1556 Tcl_ConditionFinalize(&cond);
1557 }
1558 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001559#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001560 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001561
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001562 objv = Tkapp_CallArgs(args, objStore, &objc);
1563 if (!objv)
1564 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001565
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001567
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001569
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001570 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001571
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001572 if (i == TCL_ERROR)
1573 Tkinter_Error(selfptr);
1574 else
1575 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001576
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001577 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001579 Tkapp_CallDeallocArgs(objv, objStore, objc);
1580 }
1581 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001582}
1583
1584
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001585/*[clinic input]
1586_tkinter.tkapp.eval
1587
1588 script: str
1589 /
1590
1591[clinic start generated code]*/
1592
Barry Warsawfa701a81997-01-16 00:15:11 +00001593static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001594_tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1595/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001596{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001597 PyObject *res = NULL;
1598 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001599
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001600 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001601 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001602
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001603 ENTER_TCL
1604 err = Tcl_Eval(Tkapp_Interp(self), script);
1605 ENTER_OVERLAP
1606 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001607 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001608 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001609 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001610 LEAVE_OVERLAP_TCL
1611 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001612}
1613
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001614/*[clinic input]
1615_tkinter.tkapp.evalfile
1616
1617 fileName: str
1618 /
1619
1620[clinic start generated code]*/
1621
Guido van Rossum18468821994-06-20 07:49:28 +00001622static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001623_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1624/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001625{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001626 PyObject *res = NULL;
1627 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001628
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001629 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001630 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001632 ENTER_TCL
1633 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1634 ENTER_OVERLAP
1635 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001636 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001637 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001638 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001639 LEAVE_OVERLAP_TCL
1640 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001641}
1642
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001643/*[clinic input]
1644_tkinter.tkapp.record
1645
1646 script: str
1647 /
1648
1649[clinic start generated code]*/
1650
Guido van Rossum18468821994-06-20 07:49:28 +00001651static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001652_tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1653/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001654{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001655 PyObject *res = NULL;
1656 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001657
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001658 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001659 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001661 ENTER_TCL
1662 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1663 ENTER_OVERLAP
1664 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001665 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001666 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001667 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001668 LEAVE_OVERLAP_TCL
1669 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001670}
1671
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001672/*[clinic input]
1673_tkinter.tkapp.adderrinfo
Guido van Rossum18468821994-06-20 07:49:28 +00001674
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001675 msg: str
1676 /
1677
1678[clinic start generated code]*/
1679
1680static PyObject *
1681_tkinter_tkapp_adderrinfo_impl(TkappObject *self, const char *msg)
1682/*[clinic end generated code: output=0e222ee2050eb357 input=4971399317d4c136]*/
1683{
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001684 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001685 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001686
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001687 ENTER_TCL
1688 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1689 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001690
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001691 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001692}
1693
Barry Warsawfa701a81997-01-16 00:15:11 +00001694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001695
Guido van Rossum18468821994-06-20 07:49:28 +00001696/** Tcl Variable **/
1697
Benjamin Peterson5879d412009-03-30 14:51:56 +00001698typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1699
1700#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001701TCL_DECLARE_MUTEX(var_mutex)
1702
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001703typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001704 Tcl_Event ev; /* must be first */
1705 PyObject *self;
1706 PyObject *args;
1707 int flags;
1708 EventFunc func;
1709 PyObject **res;
1710 PyObject **exc_type;
1711 PyObject **exc_val;
1712 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001713} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001714#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001715
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001716/*[python]
1717
1718class varname_converter(CConverter):
1719 type = 'const char *'
1720 converter = 'varname_converter'
1721
1722[python]*/
1723/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1724
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001725static int
1726varname_converter(PyObject *in, void *_out)
1727{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001728 char *s;
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001729 const char **out = (const char**)_out;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001730 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001731 if (PyBytes_Size(in) > INT_MAX) {
1732 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1733 return 0;
1734 }
1735 s = PyBytes_AsString(in);
Victor Stinner706768c2014-08-16 01:03:39 +02001736 if (strlen(s) != (size_t)PyBytes_Size(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001737 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001738 return 0;
1739 }
1740 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001741 return 1;
1742 }
1743 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001744 Py_ssize_t size;
1745 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001746 if (s == NULL) {
1747 return 0;
1748 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001749 if (size > INT_MAX) {
1750 PyErr_SetString(PyExc_OverflowError, "string is too long");
1751 return 0;
1752 }
Victor Stinner706768c2014-08-16 01:03:39 +02001753 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001754 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001755 return 0;
1756 }
1757 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001758 return 1;
1759 }
1760 if (PyTclObject_Check(in)) {
1761 *out = PyTclObject_TclString(in);
1762 return 1;
1763 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001764 PyErr_Format(PyExc_TypeError,
1765 "must be str, bytes or Tcl_Obj, not %.50s",
1766 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001767 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001768}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001769
Benjamin Peterson5879d412009-03-30 14:51:56 +00001770#ifdef WITH_THREAD
1771
Martin v. Löwis59683e82008-06-13 07:50:45 +00001772static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001773var_perform(VarEvent *ev)
1774{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1776 if (!*(ev->res)) {
1777 PyObject *exc, *val, *tb;
1778 PyErr_Fetch(&exc, &val, &tb);
1779 PyErr_NormalizeException(&exc, &val, &tb);
1780 *(ev->exc_type) = exc;
1781 *(ev->exc_val) = val;
1782 Py_DECREF(tb);
1783 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001784
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001785}
1786
1787static int
1788var_proc(VarEvent* ev, int flags)
1789{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001790 ENTER_PYTHON
1791 var_perform(ev);
1792 Tcl_MutexLock(&var_mutex);
1793 Tcl_ConditionNotify(ev->cond);
1794 Tcl_MutexUnlock(&var_mutex);
1795 LEAVE_PYTHON
1796 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001797}
1798
Benjamin Peterson5879d412009-03-30 14:51:56 +00001799#endif
1800
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001801static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001802var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001803{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001804#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001805 TkappObject *self = (TkappObject*)selfptr;
1806 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001807 VarEvent *ev;
1808 PyObject *res, *exc_type, *exc_val;
1809 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001810
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001811 /* The current thread is not the interpreter thread. Marshal
1812 the call to the interpreter thread, then wait for
1813 completion. */
1814 if (!WaitForMainloop(self))
1815 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001816
Serhiy Storchaka07940882014-09-11 10:38:54 +03001817 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1818 if (ev == NULL) {
1819 PyErr_NoMemory();
1820 return NULL;
1821 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001822 ev->self = selfptr;
1823 ev->args = args;
1824 ev->flags = flags;
1825 ev->func = func;
1826 ev->res = &res;
1827 ev->exc_type = &exc_type;
1828 ev->exc_val = &exc_val;
1829 ev->cond = &cond;
1830 ev->ev.proc = (Tcl_EventProc*)var_proc;
1831 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1832 Tcl_ConditionFinalize(&cond);
1833 if (!res) {
1834 PyErr_SetObject(exc_type, exc_val);
1835 Py_DECREF(exc_type);
1836 Py_DECREF(exc_val);
1837 return NULL;
1838 }
1839 return res;
1840 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001841#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001842 /* Tcl is not threaded, or this is the interpreter thread. */
1843 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001844}
1845
Guido van Rossum18468821994-06-20 07:49:28 +00001846static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001847SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001848{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001849 const char *name1, *name2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001850 PyObject *newValue;
1851 PyObject *res = NULL;
1852 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001853
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001854 switch (PyTuple_GET_SIZE(args)) {
1855 case 2:
1856 if (!PyArg_ParseTuple(args, "O&O:setvar",
1857 varname_converter, &name1, &newValue))
1858 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001859 /* XXX Acquire tcl lock??? */
1860 newval = AsObj(newValue);
1861 if (newval == NULL)
1862 return NULL;
1863 ENTER_TCL
1864 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1865 newval, flags);
1866 ENTER_OVERLAP
1867 if (!ok)
1868 Tkinter_Error(self);
1869 else {
1870 res = Py_None;
1871 Py_INCREF(res);
1872 }
1873 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001874 break;
1875 case 3:
1876 if (!PyArg_ParseTuple(args, "ssO:setvar",
1877 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001878 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001879 CHECK_STRING_LENGTH(name1);
1880 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001881 /* XXX must hold tcl lock already??? */
1882 newval = AsObj(newValue);
1883 ENTER_TCL
1884 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1885 ENTER_OVERLAP
1886 if (!ok)
1887 Tkinter_Error(self);
1888 else {
1889 res = Py_None;
1890 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001891 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001892 LEAVE_OVERLAP_TCL
1893 break;
1894 default:
1895 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1896 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001897 }
1898 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001899}
1900
1901static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001902Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001903{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001904 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001905}
1906
1907static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001908Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001909{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001910 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001911}
1912
Barry Warsawfa701a81997-01-16 00:15:11 +00001913
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001914
Guido van Rossum18468821994-06-20 07:49:28 +00001915static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001916GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001917{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001918 const char *name1, *name2=NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001919 PyObject *res = NULL;
1920 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001921
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001922 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1923 varname_converter, &name1, &name2))
1924 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001925
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001926 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001927 ENTER_TCL
1928 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1929 ENTER_OVERLAP
1930 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001931 PyErr_SetString(Tkinter_TclError,
1932 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001933 } else {
1934 if (((TkappObject*)self)->wantobjects) {
1935 res = FromObj(self, tres);
1936 }
1937 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001938 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001939 }
1940 }
1941 LEAVE_OVERLAP_TCL
1942 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001943}
1944
1945static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001946Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001947{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001948 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001949}
1950
1951static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001952Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001953{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001954 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001955}
1956
Barry Warsawfa701a81997-01-16 00:15:11 +00001957
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001958
Guido van Rossum18468821994-06-20 07:49:28 +00001959static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001960UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001961{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001962 char *name1, *name2=NULL;
1963 int code;
1964 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001965
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001966 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1967 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001968
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001969 CHECK_STRING_LENGTH(name1);
1970 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001971 ENTER_TCL
1972 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1973 ENTER_OVERLAP
1974 if (code == TCL_ERROR)
1975 res = Tkinter_Error(self);
1976 else {
1977 Py_INCREF(Py_None);
1978 res = Py_None;
1979 }
1980 LEAVE_OVERLAP_TCL
1981 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001982}
1983
1984static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001985Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001986{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001987 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001988}
1989
1990static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001991Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001992{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001993 return var_invoke(UnsetVar, self, args,
1994 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001995}
1996
Barry Warsawfa701a81997-01-16 00:15:11 +00001997
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001998
Guido van Rossum18468821994-06-20 07:49:28 +00001999/** Tcl to Python **/
2000
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002001/*[clinic input]
2002_tkinter.tkapp.getint
2003
2004 arg: object
2005 /
2006
2007[clinic start generated code]*/
2008
Guido van Rossum18468821994-06-20 07:49:28 +00002009static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002010_tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
2011/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002012{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002013 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002014 Tcl_Obj *value;
2015 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00002016
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002017 if (PyLong_Check(arg)) {
2018 Py_INCREF(arg);
2019 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002020 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002021
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002022 if (PyTclObject_Check(arg)) {
2023 value = ((PyTclObject*)arg)->value;
2024 Tcl_IncrRefCount(value);
2025 }
2026 else {
2027 if (!PyArg_Parse(arg, "s:getint", &s))
2028 return NULL;
2029 CHECK_STRING_LENGTH(s);
2030 value = Tcl_NewStringObj(s, -1);
2031 if (value == NULL)
2032 return Tkinter_Error((PyObject *)self);
2033 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002034 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
2035 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
2036
2037 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
2038 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
2039 */
2040#ifdef HAVE_LIBTOMMAMTH
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002041 result = fromBignumObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002042#else
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002043 result = fromWideIntObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002044#endif
2045 Tcl_DecrRefCount(value);
2046 if (result != NULL || PyErr_Occurred())
2047 return result;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002048 return Tkinter_Error((PyObject *)self);
Guido van Rossum18468821994-06-20 07:49:28 +00002049}
2050
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002051/*[clinic input]
2052_tkinter.tkapp.getdouble
2053
2054 arg: object
2055 /
2056
2057[clinic start generated code]*/
2058
Guido van Rossum18468821994-06-20 07:49:28 +00002059static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002060_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
2061/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002062{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063 char *s;
2064 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00002065
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002066 if (PyFloat_Check(arg)) {
2067 Py_INCREF(arg);
2068 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002069 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002070
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002071 if (PyNumber_Check(arg)) {
2072 return PyNumber_Float(arg);
2073 }
2074
2075 if (PyTclObject_Check(arg)) {
2076 if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
2077 ((PyTclObject*)arg)->value,
2078 &v) == TCL_ERROR)
2079 return Tkinter_Error((PyObject *)self);
2080 return PyFloat_FromDouble(v);
2081 }
2082
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002083 if (!PyArg_Parse(arg, "s:getdouble", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002084 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002085 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002086 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002087 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002088 return PyFloat_FromDouble(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002089}
2090
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002091/*[clinic input]
2092_tkinter.tkapp.getboolean
2093
2094 arg: object
2095 /
2096
2097[clinic start generated code]*/
2098
Guido van Rossum18468821994-06-20 07:49:28 +00002099static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002100_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
2101/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002102{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002103 char *s;
2104 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002105
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002106 if (PyLong_Check(arg)) { /* int or bool */
2107 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002108 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002109
2110 if (PyTclObject_Check(arg)) {
2111 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2112 ((PyTclObject*)arg)->value,
2113 &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002114 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002115 return PyBool_FromLong(v);
2116 }
2117
2118 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002119 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002120 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002121 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002122 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002123 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002124}
2125
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002126/*[clinic input]
2127_tkinter.tkapp.exprstring
2128
2129 s: str
2130 /
2131
2132[clinic start generated code]*/
2133
Guido van Rossum18468821994-06-20 07:49:28 +00002134static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002135_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2136/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002137{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 PyObject *res = NULL;
2139 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002140
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002141 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002143
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002144 ENTER_TCL
2145 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2146 ENTER_OVERLAP
2147 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002148 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002149 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002150 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002151 LEAVE_OVERLAP_TCL
2152 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002153}
2154
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002155/*[clinic input]
2156_tkinter.tkapp.exprlong
2157
2158 s: str
2159 /
2160
2161[clinic start generated code]*/
2162
Guido van Rossum18468821994-06-20 07:49:28 +00002163static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002164_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2165/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002166{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002167 PyObject *res = NULL;
2168 int retval;
2169 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002170
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002171 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002172 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002173
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002174 ENTER_TCL
2175 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2176 ENTER_OVERLAP
2177 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002178 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002179 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002180 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002181 LEAVE_OVERLAP_TCL
2182 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002183}
2184
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002185/*[clinic input]
2186_tkinter.tkapp.exprdouble
2187
2188 s: str
2189 /
2190
2191[clinic start generated code]*/
2192
Guido van Rossum18468821994-06-20 07:49:28 +00002193static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002194_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2195/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002196{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 PyObject *res = NULL;
2198 double v;
2199 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002200
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002201 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002202 CHECK_TCL_APPARTMENT;
2203 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2204 ENTER_TCL
2205 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2206 ENTER_OVERLAP
2207 PyFPE_END_PROTECT(retval)
2208 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002209 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002210 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002211 res = PyFloat_FromDouble(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002212 LEAVE_OVERLAP_TCL
2213 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002214}
2215
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002216/*[clinic input]
2217_tkinter.tkapp.exprboolean
2218
2219 s: str
2220 /
2221
2222[clinic start generated code]*/
2223
Guido van Rossum18468821994-06-20 07:49:28 +00002224static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002225_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2226/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002227{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002228 PyObject *res = NULL;
2229 int retval;
2230 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002231
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002232 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002233 CHECK_TCL_APPARTMENT;
2234 ENTER_TCL
2235 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2236 ENTER_OVERLAP
2237 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002238 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002239 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002240 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002241 LEAVE_OVERLAP_TCL
2242 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002243}
2244
Barry Warsawfa701a81997-01-16 00:15:11 +00002245
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002246
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002247/*[clinic input]
2248_tkinter.tkapp.splitlist
2249
2250 arg: object
2251 /
2252
2253[clinic start generated code]*/
2254
Guido van Rossum18468821994-06-20 07:49:28 +00002255static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002256_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2257/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002258{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002259 char *list;
2260 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002261 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002262 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002263 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002264
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002265 if (PyTclObject_Check(arg)) {
2266 int objc;
2267 Tcl_Obj **objv;
2268 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2269 ((PyTclObject*)arg)->value,
2270 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002271 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002272 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002273 if (!(v = PyTuple_New(objc)))
2274 return NULL;
2275 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002276 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002277 if (!s || PyTuple_SetItem(v, i, s)) {
2278 Py_DECREF(v);
2279 return NULL;
2280 }
2281 }
2282 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002283 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002284 if (PyTuple_Check(arg)) {
2285 Py_INCREF(arg);
2286 return arg;
2287 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002288 if (PyList_Check(arg)) {
2289 return PySequence_Tuple(arg);
2290 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002291
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002292 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002293 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002294
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002295 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002296 if (Tcl_SplitList(Tkapp_Interp(self), list,
2297 &argc, &argv) == TCL_ERROR) {
2298 PyMem_Free(list);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002299 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002300 }
Guido van Rossum18468821994-06-20 07:49:28 +00002301
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002302 if (!(v = PyTuple_New(argc)))
2303 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002304
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002305 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002306 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002307 if (!s || PyTuple_SetItem(v, i, s)) {
2308 Py_DECREF(v);
2309 v = NULL;
2310 goto finally;
2311 }
2312 }
Guido van Rossum18468821994-06-20 07:49:28 +00002313
Barry Warsawfa701a81997-01-16 00:15:11 +00002314 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002315 ckfree(FREECAST argv);
2316 PyMem_Free(list);
2317 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002318}
2319
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002320/*[clinic input]
2321_tkinter.tkapp.split
2322
2323 arg: object
2324 /
2325
2326[clinic start generated code]*/
2327
Guido van Rossum18468821994-06-20 07:49:28 +00002328static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002329_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2330/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002331{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002332 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002333 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002334
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002335 if (PyTclObject_Check(arg)) {
2336 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2337 int objc;
2338 Tcl_Obj **objv;
2339 int i;
2340 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2341 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002342 return FromObj((PyObject*)self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002343 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002344 if (objc == 0)
2345 return PyUnicode_FromString("");
2346 if (objc == 1)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002347 return FromObj((PyObject*)self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002348 if (!(v = PyTuple_New(objc)))
2349 return NULL;
2350 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002351 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002352 if (!s || PyTuple_SetItem(v, i, s)) {
2353 Py_DECREF(v);
2354 return NULL;
2355 }
2356 }
2357 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002358 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002359 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002360 return SplitObj(arg);
2361
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002362 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002363 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002364 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002365 v = Split(list);
2366 PyMem_Free(list);
2367 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002368}
2369
Barry Warsawfa701a81997-01-16 00:15:11 +00002370
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002371
Guido van Rossum18468821994-06-20 07:49:28 +00002372/** Tcl Command **/
2373
Guido van Rossum00d93061998-05-28 23:06:38 +00002374/* Client data struct */
2375typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002376 PyObject *self;
2377 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002378} PythonCmd_ClientData;
2379
2380static int
Fred Drake509d79a2000-07-08 04:04:38 +00002381PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002382{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002383 errorInCmd = 1;
2384 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2385 LEAVE_PYTHON
2386 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002387}
2388
Guido van Rossum18468821994-06-20 07:49:28 +00002389/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002390 * function or method.
2391 */
Guido van Rossum18468821994-06-20 07:49:28 +00002392static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002393PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002394{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002395 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002396 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002397 int i, rv;
2398 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002399
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002400 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002401
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002402 /* TBD: no error checking here since we know, via the
2403 * Tkapp_CreateCommand() that the client data is a two-tuple
2404 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002405 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 /* Create argument list (argv1, ..., argvN) */
2408 if (!(arg = PyTuple_New(argc - 1)))
2409 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002411 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002412 PyObject *s = unicodeFromTclString(argv[i + 1]);
2413 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002414 Py_DECREF(arg);
2415 return PythonCmd_Error(interp);
2416 }
2417 }
2418 res = PyEval_CallObject(func, arg);
2419 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002421 if (res == NULL)
2422 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002423
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002424 obj_res = AsObj(res);
2425 if (obj_res == NULL) {
2426 Py_DECREF(res);
2427 return PythonCmd_Error(interp);
2428 }
2429 else {
2430 Tcl_SetObjResult(interp, obj_res);
2431 rv = TCL_OK;
2432 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002433
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002434 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002435
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002436 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002438 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002439}
2440
2441static void
Fred Drake509d79a2000-07-08 04:04:38 +00002442PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002443{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002444 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002445
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002446 ENTER_PYTHON
2447 Py_XDECREF(data->self);
2448 Py_XDECREF(data->func);
2449 PyMem_DEL(data);
2450 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002451}
2452
Barry Warsawfa701a81997-01-16 00:15:11 +00002453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002454
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002455
Benjamin Peterson5879d412009-03-30 14:51:56 +00002456#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002457TCL_DECLARE_MUTEX(command_mutex)
2458
2459typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002460 Tcl_Event ev;
2461 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002462 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002463 int create;
2464 int *status;
2465 ClientData *data;
2466 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002467} CommandEvent;
2468
2469static int
2470Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002471{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002472 if (ev->create)
2473 *ev->status = Tcl_CreateCommand(
2474 ev->interp, ev->name, PythonCmd,
2475 ev->data, PythonCmdDelete) == NULL;
2476 else
2477 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2478 Tcl_MutexLock(&command_mutex);
2479 Tcl_ConditionNotify(ev->done);
2480 Tcl_MutexUnlock(&command_mutex);
2481 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002482}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002483#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002484
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002485/*[clinic input]
2486_tkinter.tkapp.createcommand
2487
2488 self: self(type="TkappObject *")
2489 name: str
2490 func: object
2491 /
2492
2493[clinic start generated code]*/
2494
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002495static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002496_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2497 PyObject *func)
2498/*[clinic end generated code: output=2a1c79a4ee2af410 input=2bc2c046a0914234]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002499{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002500 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002501 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002502
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002503 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002504 if (!PyCallable_Check(func)) {
2505 PyErr_SetString(PyExc_TypeError, "command not callable");
2506 return NULL;
2507 }
Guido van Rossum18468821994-06-20 07:49:28 +00002508
Martin v. Löwisa9656492003-03-30 08:44:58 +00002509#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002510 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2511 !WaitForMainloop(self))
2512 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002513#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002514
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002515 data = PyMem_NEW(PythonCmd_ClientData, 1);
2516 if (!data)
2517 return PyErr_NoMemory();
2518 Py_INCREF(self);
2519 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002520 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002521 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002522#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002523 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2524 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002525 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2526 if (ev == NULL) {
2527 PyErr_NoMemory();
2528 PyMem_DEL(data);
2529 return NULL;
2530 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002531 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2532 ev->interp = self->interp;
2533 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002534 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002535 ev->data = (ClientData)data;
2536 ev->status = &err;
2537 ev->done = &cond;
2538 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2539 Tcl_ConditionFinalize(&cond);
2540 }
2541 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002542#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002543 {
2544 ENTER_TCL
2545 err = Tcl_CreateCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002546 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002547 (ClientData)data, PythonCmdDelete) == NULL;
2548 LEAVE_TCL
2549 }
2550 if (err) {
2551 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2552 PyMem_DEL(data);
2553 return NULL;
2554 }
Guido van Rossum18468821994-06-20 07:49:28 +00002555
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002556 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002557}
2558
Barry Warsawfa701a81997-01-16 00:15:11 +00002559
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002561/*[clinic input]
2562_tkinter.tkapp.deletecommand
2563
2564 self: self(type="TkappObject *")
2565 name: str
2566 /
2567
2568[clinic start generated code]*/
2569
Guido van Rossum18468821994-06-20 07:49:28 +00002570static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002571_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
2572/*[clinic end generated code: output=a67e8cb5845e0d2d input=b6306468f10b219c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002573{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002574 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002575
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002576 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002577
2578#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2580 Tcl_Condition cond = NULL;
2581 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002582 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2583 if (ev == NULL) {
2584 PyErr_NoMemory();
2585 return NULL;
2586 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002587 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2588 ev->interp = self->interp;
2589 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002590 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002591 ev->status = &err;
2592 ev->done = &cond;
2593 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2594 &command_mutex);
2595 Tcl_ConditionFinalize(&cond);
2596 }
2597 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002598#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002599 {
2600 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002601 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002602 LEAVE_TCL
2603 }
2604 if (err == -1) {
2605 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2606 return NULL;
2607 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002608 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002609}
2610
Barry Warsawfa701a81997-01-16 00:15:11 +00002611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002612
Guido van Rossum00d93061998-05-28 23:06:38 +00002613#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002614/** File Handler **/
2615
Guido van Rossum00d93061998-05-28 23:06:38 +00002616typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002617 PyObject *func;
2618 PyObject *file;
2619 int id;
2620 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002621} FileHandler_ClientData;
2622
2623static FileHandler_ClientData *HeadFHCD;
2624
2625static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002626NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002627{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002628 FileHandler_ClientData *p;
2629 p = PyMem_NEW(FileHandler_ClientData, 1);
2630 if (p != NULL) {
2631 Py_XINCREF(func);
2632 Py_XINCREF(file);
2633 p->func = func;
2634 p->file = file;
2635 p->id = id;
2636 p->next = HeadFHCD;
2637 HeadFHCD = p;
2638 }
2639 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002640}
2641
2642static void
Fred Drake509d79a2000-07-08 04:04:38 +00002643DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002644{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002645 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002647 pp = &HeadFHCD;
2648 while ((p = *pp) != NULL) {
2649 if (p->id == id) {
2650 *pp = p->next;
2651 Py_XDECREF(p->func);
2652 Py_XDECREF(p->file);
2653 PyMem_DEL(p);
2654 }
2655 else
2656 pp = &p->next;
2657 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002658}
2659
Guido van Rossuma597dde1995-01-10 20:56:29 +00002660static void
Fred Drake509d79a2000-07-08 04:04:38 +00002661FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002662{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002663 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2664 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002666 ENTER_PYTHON
2667 func = data->func;
2668 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002670 arg = Py_BuildValue("(Oi)", file, (long) mask);
2671 res = PyEval_CallObject(func, arg);
2672 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002674 if (res == NULL) {
2675 errorInCmd = 1;
2676 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2677 }
2678 Py_XDECREF(res);
2679 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002680}
2681
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002682/*[clinic input]
2683_tkinter.tkapp.createfilehandler
2684
2685 file: object
2686 mask: int
2687 func: object
2688 /
2689
2690[clinic start generated code]*/
2691
Guido van Rossum18468821994-06-20 07:49:28 +00002692static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002693_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2694 int mask, PyObject *func)
2695/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002696{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002697 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002698 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002700 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002702 tfile = PyObject_AsFileDescriptor(file);
2703 if (tfile < 0)
2704 return NULL;
2705 if (!PyCallable_Check(func)) {
2706 PyErr_SetString(PyExc_TypeError, "bad argument list");
2707 return NULL;
2708 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002709
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002710 data = NewFHCD(func, file, tfile);
2711 if (data == NULL)
2712 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002713
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002714 /* Ought to check for null Tcl_File object... */
2715 ENTER_TCL
2716 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2717 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002718 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002719}
2720
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002721/*[clinic input]
2722_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002723
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002724 file: object
2725 /
2726
2727[clinic start generated code]*/
2728
2729static PyObject *
2730_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2731/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2732{
2733 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002734
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002735 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002736
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002737 tfile = PyObject_AsFileDescriptor(file);
2738 if (tfile < 0)
2739 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002743 /* Ought to check for null Tcl_File object... */
2744 ENTER_TCL
2745 Tcl_DeleteFileHandler(tfile);
2746 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002747 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002748}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002749#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002750
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002751
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002752/**** Tktt Object (timer token) ****/
2753
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002754static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002755
Guido van Rossum00d93061998-05-28 23:06:38 +00002756typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002757 PyObject_HEAD
2758 Tcl_TimerToken token;
2759 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002760} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002761
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002762/*[clinic input]
2763_tkinter.tktimertoken.deletetimerhandler
2764
2765 self: self(type="TkttObject *")
2766
2767[clinic start generated code]*/
2768
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002769static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002770_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
2771/*[clinic end generated code: output=bd7fe17f328cfa55 input=25ba5dd594e52084]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002772{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002773 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002774 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002775
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002776 if (v->token != NULL) {
2777 Tcl_DeleteTimerHandler(v->token);
2778 v->token = NULL;
2779 }
2780 if (func != NULL) {
2781 v->func = NULL;
2782 Py_DECREF(func);
2783 Py_DECREF(v); /* See Tktt_New() */
2784 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002785 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002786}
2787
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002788static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002789Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002790{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002791 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002792
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002793 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 if (v == NULL)
2795 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002796 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002798 Py_INCREF(func);
2799 v->token = NULL;
2800 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002801
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002802 /* Extra reference, deleted when called or when handler is deleted */
2803 Py_INCREF(v);
2804 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002805}
2806
2807static void
Fred Drake509d79a2000-07-08 04:04:38 +00002808Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002809{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002810 TkttObject *v = (TkttObject *)self;
2811 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002812 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002813
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002814 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002815
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002816 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002817 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002818}
2819
Guido van Rossum597ac201998-05-12 14:36:19 +00002820static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002821Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002822{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002823 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002824 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2825 v,
2826 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002827}
2828
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002829/** Timer Handler **/
2830
2831static void
Fred Drake509d79a2000-07-08 04:04:38 +00002832TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002833{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002834 TkttObject *v = (TkttObject *)clientData;
2835 PyObject *func = v->func;
2836 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002837
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002838 if (func == NULL)
2839 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002840
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002841 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002842
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002843 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002844
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002845 res = PyEval_CallObject(func, NULL);
2846 Py_DECREF(func);
2847 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002848
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002849 if (res == NULL) {
2850 errorInCmd = 1;
2851 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2852 }
2853 else
2854 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002855
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002856 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002857}
2858
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002859/*[clinic input]
2860_tkinter.tkapp.createtimerhandler
2861
2862 milliseconds: int
2863 func: object
2864 /
2865
2866[clinic start generated code]*/
2867
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002868static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002869_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2870 PyObject *func)
2871/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002872{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002873 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002874
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002875 if (!PyCallable_Check(func)) {
2876 PyErr_SetString(PyExc_TypeError, "bad argument list");
2877 return NULL;
2878 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002879
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002880 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002881
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002882 v = Tktt_New(func);
2883 if (v) {
2884 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2885 (ClientData)v);
2886 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002888 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002889}
2890
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002891
Guido van Rossum18468821994-06-20 07:49:28 +00002892/** Event Loop **/
2893
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002894/*[clinic input]
2895_tkinter.tkapp.mainloop
2896
2897 self: self(type="TkappObject *")
2898 threshold: int = 0
2899 /
2900
2901[clinic start generated code]*/
2902
Guido van Rossum18468821994-06-20 07:49:28 +00002903static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002904_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
2905/*[clinic end generated code: output=0ba8eabbe57841b0 input=ad57c9c1dd2b9470]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002906{
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002907#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002908 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002909#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002910
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002911 CHECK_TCL_APPARTMENT;
2912 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002913
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002914 quitMainLoop = 0;
2915 while (Tk_GetNumMainWindows() > threshold &&
2916 !quitMainLoop &&
2917 !errorInCmd)
2918 {
2919 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002920
2921#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002922 if (self->threaded) {
2923 /* Allow other Python threads to run. */
2924 ENTER_TCL
2925 result = Tcl_DoOneEvent(0);
2926 LEAVE_TCL
2927 }
2928 else {
2929 Py_BEGIN_ALLOW_THREADS
2930 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2931 tcl_tstate = tstate;
2932 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2933 tcl_tstate = NULL;
2934 if(tcl_lock)PyThread_release_lock(tcl_lock);
2935 if (result == 0)
2936 Sleep(Tkinter_busywaitinterval);
2937 Py_END_ALLOW_THREADS
2938 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002939#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002940 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002941#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002942
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002943 if (PyErr_CheckSignals() != 0) {
2944 self->dispatching = 0;
2945 return NULL;
2946 }
2947 if (result < 0)
2948 break;
2949 }
2950 self->dispatching = 0;
2951 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002952
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002953 if (errorInCmd) {
2954 errorInCmd = 0;
2955 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2956 excInCmd = valInCmd = trbInCmd = NULL;
2957 return NULL;
2958 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002959 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002960}
2961
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002962/*[clinic input]
2963_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002964
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002965 flags: int = 0
2966 /
2967
2968[clinic start generated code]*/
2969
2970static PyObject *
2971_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2972/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2973{
2974 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002975
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002976 ENTER_TCL
2977 rv = Tcl_DoOneEvent(flags);
2978 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002979 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002980}
2981
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002982/*[clinic input]
2983_tkinter.tkapp.quit
2984[clinic start generated code]*/
2985
Guido van Rossum062cfb01995-01-10 17:42:51 +00002986static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002987_tkinter_tkapp_quit_impl(TkappObject *self)
2988/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002989{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002990 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002991 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002992}
2993
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002994/*[clinic input]
2995_tkinter.tkapp.interpaddr
2996[clinic start generated code]*/
2997
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002998static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002999_tkinter_tkapp_interpaddr_impl(TkappObject *self)
3000/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003001{
Victor Stinnere1040e22013-09-05 00:22:24 +02003002 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003003}
3004
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003005/*[clinic input]
3006_tkinter.tkapp.loadtk
3007[clinic start generated code]*/
3008
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003009static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003010_tkinter_tkapp_loadtk_impl(TkappObject *self)
3011/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00003012{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003013 Tcl_Interp *interp = Tkapp_Interp(self);
3014 const char * _tk_exists = NULL;
3015 int err;
David Aschere2b4b322004-02-18 05:59:53 +00003016
Guilherme Polob681df42009-02-09 22:33:59 +00003017#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003018 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
3019 * first call failed.
3020 * To avoid the deadlock, we just refuse the second call through
3021 * a static variable.
3022 */
3023 if (tk_load_failed) {
3024 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
3025 return NULL;
3026 }
Guilherme Polob681df42009-02-09 22:33:59 +00003027#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003028
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003029 /* We want to guard against calling Tk_Init() multiple times */
3030 CHECK_TCL_APPARTMENT;
3031 ENTER_TCL
3032 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
3033 ENTER_OVERLAP
3034 if (err == TCL_ERROR) {
3035 /* This sets an exception, but we cannot return right
3036 away because we need to exit the overlap first. */
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003037 Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003038 } else {
3039 _tk_exists = Tkapp_Result(self);
3040 }
3041 LEAVE_OVERLAP_TCL
3042 if (err == TCL_ERROR) {
3043 return NULL;
3044 }
3045 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
3046 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003047 PyErr_SetString(Tkinter_TclError,
3048 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00003049#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003050 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00003051#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003052 return NULL;
3053 }
3054 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003055 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00003056}
Barry Warsawfa701a81997-01-16 00:15:11 +00003057
Martin v. Löwisffad6332002-11-26 09:28:05 +00003058static PyObject *
3059Tkapp_WantObjects(PyObject *self, PyObject *args)
3060{
3061
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003062 int wantobjects = -1;
3063 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3064 return NULL;
3065 if (wantobjects == -1)
3066 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3067 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003068
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003069 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003070}
3071
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003072/*[clinic input]
3073_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003074
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003075 self: self(type="TkappObject *")
3076
3077[clinic start generated code]*/
3078
3079static PyObject *
3080_tkinter_tkapp_willdispatch_impl(TkappObject *self)
3081/*[clinic end generated code: output=0e3f46d244642155 input=2630699767808970]*/
3082{
3083 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003084
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003085 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003086}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003088
Guido van Rossum18468821994-06-20 07:49:28 +00003089/**** Tkapp Type Methods ****/
3090
3091static void
Fred Drake509d79a2000-07-08 04:04:38 +00003092Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003093{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003094 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003095 /*CHECK_TCL_APPARTMENT;*/
3096 ENTER_TCL
3097 Tcl_DeleteInterp(Tkapp_Interp(self));
3098 LEAVE_TCL
3099 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003100 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003101 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003102}
3103
Barry Warsawfa701a81997-01-16 00:15:11 +00003104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003105
Guido van Rossum18468821994-06-20 07:49:28 +00003106/**** Tkinter Module ****/
3107
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003108typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003109 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003110 Py_ssize_t size; /* current size */
3111 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003112} FlattenContext;
3113
3114static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003115_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003116{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003117 /* expand tuple to hold (at least) size new items.
3118 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003119
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003120 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003121
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003122 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003123 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003124
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003125 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003126
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003127 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003128}
3129
3130static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003131_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003132{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003133 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003134
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003135 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003136
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003137 if (depth > 1000) {
3138 PyErr_SetString(PyExc_ValueError,
3139 "nesting too deep in _flatten");
3140 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003141 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3142 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003143 /* preallocate (assume no nesting) */
3144 if (context->size + size > context->maxsize &&
3145 !_bump(context, size))
3146 return 0;
3147 /* copy items to output tuple */
3148 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003149 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003150 if (PyList_Check(o) || PyTuple_Check(o)) {
3151 if (!_flatten1(context, o, depth + 1))
3152 return 0;
3153 } else if (o != Py_None) {
3154 if (context->size + 1 > context->maxsize &&
3155 !_bump(context, 1))
3156 return 0;
3157 Py_INCREF(o);
3158 PyTuple_SET_ITEM(context->tuple,
3159 context->size++, o);
3160 }
3161 }
3162 } else {
3163 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3164 return 0;
3165 }
3166 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003167}
3168
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003169/*[clinic input]
3170_tkinter._flatten
3171
3172 item: object
3173 /
3174
3175[clinic start generated code]*/
3176
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003177static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003178_tkinter__flatten(PyModuleDef *module, PyObject *item)
3179/*[clinic end generated code: output=9505049ec74c3480 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003180{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003181 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003182
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003183 context.maxsize = PySequence_Size(item);
3184 if (context.maxsize < 0)
3185 return NULL;
3186 if (context.maxsize == 0)
3187 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003188
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003189 context.tuple = PyTuple_New(context.maxsize);
3190 if (!context.tuple)
3191 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003192
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003193 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003195 if (!_flatten1(&context, item,0))
3196 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003198 if (_PyTuple_Resize(&context.tuple, context.size))
3199 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003200
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003201 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003202}
3203
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003204/*[clinic input]
3205_tkinter.create
3206
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003207 screenName: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003208 baseName: str = NULL
3209 className: str = "Tk"
3210 interactive: int(c_default="0") = False
3211 wantobjects: int(c_default="0") = False
3212 wantTk: int(c_default="1") = True
3213 if false, then Tk_Init() doesn't get called
3214 sync: int(c_default="0") = False
3215 if true, then pass -sync to wish
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003216 use: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003217 if not None, then pass -use to wish
3218 /
3219
3220[clinic start generated code]*/
3221
Guido van Rossum18468821994-06-20 07:49:28 +00003222static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003223_tkinter_create_impl(PyModuleDef *module, const char *screenName,
3224 const char *baseName, const char *className,
3225 int interactive, int wantobjects, int wantTk, int sync,
3226 const char *use)
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003227/*[clinic end generated code: output=b8847800fc3b27eb input=0d522aad1cb0ca0e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003228{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003229 /* XXX baseName is not used anymore;
3230 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003231 CHECK_STRING_LENGTH(screenName);
3232 CHECK_STRING_LENGTH(baseName);
3233 CHECK_STRING_LENGTH(className);
3234 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003236 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003237 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003238 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003239}
3240
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003241/*[clinic input]
3242_tkinter.setbusywaitinterval
3243
3244 new_val: int
3245 /
3246
3247Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3248
3249It should be set to a divisor of the maximum time between frames in an animation.
3250[clinic start generated code]*/
3251
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003252static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003253_tkinter_setbusywaitinterval_impl(PyModuleDef *module, int new_val)
3254/*[clinic end generated code: output=0b9d7ef7940461ea input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003255{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003256 if (new_val < 0) {
3257 PyErr_SetString(PyExc_ValueError,
3258 "busywaitinterval must be >= 0");
3259 return NULL;
3260 }
3261 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003262 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003263}
3264
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003265/*[clinic input]
3266_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003267
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003268Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3269[clinic start generated code]*/
3270
3271static int
3272_tkinter_getbusywaitinterval_impl(PyModuleDef *module)
3273/*[clinic end generated code: output=9d09eee026e96971 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003274{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003275 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003276}
3277
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003278#include "clinic/_tkinter.c.h"
3279
3280static PyMethodDef Tktt_methods[] =
3281{
3282 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3283 {NULL, NULL}
3284};
3285
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003286static PyType_Slot Tktt_Type_slots[] = {
3287 {Py_tp_dealloc, Tktt_Dealloc},
3288 {Py_tp_repr, Tktt_Repr},
3289 {Py_tp_methods, Tktt_methods},
3290 {0, 0}
3291};
3292
3293static PyType_Spec Tktt_Type_spec = {
3294 "_tkinter.tktimertoken",
3295 sizeof(TkttObject),
3296 0,
3297 Py_TPFLAGS_DEFAULT,
3298 Tktt_Type_slots,
3299};
3300
3301
3302/**** Tkapp Method List ****/
3303
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003304static PyMethodDef Tkapp_methods[] =
3305{
3306 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3307 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3308 {"call", Tkapp_Call, METH_VARARGS},
3309 _TKINTER_TKAPP_EVAL_METHODDEF
3310 _TKINTER_TKAPP_EVALFILE_METHODDEF
3311 _TKINTER_TKAPP_RECORD_METHODDEF
3312 _TKINTER_TKAPP_ADDERRINFO_METHODDEF
3313 {"setvar", Tkapp_SetVar, METH_VARARGS},
3314 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3315 {"getvar", Tkapp_GetVar, METH_VARARGS},
3316 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3317 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3318 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3319 _TKINTER_TKAPP_GETINT_METHODDEF
3320 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3321 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3322 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3323 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3324 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3325 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3326 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3327 _TKINTER_TKAPP_SPLIT_METHODDEF
3328 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3329 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3330 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3331 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3332 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3333 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3334 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3335 _TKINTER_TKAPP_QUIT_METHODDEF
3336 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3337 _TKINTER_TKAPP_LOADTK_METHODDEF
3338 {NULL, NULL}
3339};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003340
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003341static PyType_Slot Tkapp_Type_slots[] = {
3342 {Py_tp_dealloc, Tkapp_Dealloc},
3343 {Py_tp_methods, Tkapp_methods},
3344 {0, 0}
3345};
3346
3347
3348static PyType_Spec Tkapp_Type_spec = {
3349 "_tkinter.tkapp",
3350 sizeof(TkappObject),
3351 0,
3352 Py_TPFLAGS_DEFAULT,
3353 Tkapp_Type_slots,
3354};
3355
Guido van Rossum18468821994-06-20 07:49:28 +00003356static PyMethodDef moduleMethods[] =
3357{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003358 _TKINTER__FLATTEN_METHODDEF
3359 _TKINTER_CREATE_METHODDEF
3360 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3361 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003362 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003363};
3364
Guido van Rossum7bf15641998-05-22 18:28:17 +00003365#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003366
3367static int stdin_ready = 0;
3368
Guido van Rossumad4db171998-06-13 13:56:28 +00003369#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003370static void
Fred Drake509d79a2000-07-08 04:04:38 +00003371MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003372{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003373 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003374}
Guido van Rossumad4db171998-06-13 13:56:28 +00003375#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003376
Martin v. Löwisa9656492003-03-30 08:44:58 +00003377#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003378static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003379#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003380
Guido van Rossum18468821994-06-20 07:49:28 +00003381static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003382EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003383{
Guido van Rossumad4db171998-06-13 13:56:28 +00003384#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003385 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003386#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003387#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003388 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003389#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003390 stdin_ready = 0;
3391 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003392#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003393 tfile = fileno(stdin);
3394 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003395#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003396 while (!errorInCmd && !stdin_ready) {
3397 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003398#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003399 if (_kbhit()) {
3400 stdin_ready = 1;
3401 break;
3402 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003403#endif
3404#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003405 Py_BEGIN_ALLOW_THREADS
3406 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3407 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003409 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003411 tcl_tstate = NULL;
3412 if(tcl_lock)PyThread_release_lock(tcl_lock);
3413 if (result == 0)
3414 Sleep(Tkinter_busywaitinterval);
3415 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003416#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003417 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003418#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003420 if (result < 0)
3421 break;
3422 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003423#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003424 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003425#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003426 if (errorInCmd) {
3427 errorInCmd = 0;
3428 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3429 excInCmd = valInCmd = trbInCmd = NULL;
3430 PyErr_Print();
3431 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003432#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003433 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003434#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003435 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003436}
Guido van Rossum18468821994-06-20 07:49:28 +00003437
Guido van Rossum00d93061998-05-28 23:06:38 +00003438#endif
3439
Guido van Rossum7bf15641998-05-22 18:28:17 +00003440static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003441EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003442{
Guido van Rossum00d93061998-05-28 23:06:38 +00003443#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003444 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003445#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003446 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003447#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003448 PyOS_InputHook = EventHook;
3449 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003450#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003451}
3452
3453static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003454DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003455{
Guido van Rossum00d93061998-05-28 23:06:38 +00003456#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003457 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3458 PyOS_InputHook = NULL;
3459 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003460#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003461}
3462
Barry Warsawfa701a81997-01-16 00:15:11 +00003463
Martin v. Löwis1a214512008-06-11 05:26:20 +00003464static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003465 PyModuleDef_HEAD_INIT,
3466 "_tkinter",
3467 NULL,
3468 -1,
3469 moduleMethods,
3470 NULL,
3471 NULL,
3472 NULL,
3473 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003474};
3475
Mark Hammond62b1ab12002-07-23 06:31:15 +00003476PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003477PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003478{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003479 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003480
Guido van Rossum00d93061998-05-28 23:06:38 +00003481#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003482 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003483 if (tcl_lock == NULL)
3484 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003485#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003487 m = PyModule_Create(&_tkintermodule);
3488 if (m == NULL)
3489 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003490
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003491 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3492 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003493 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003494 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003495 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003496 Py_INCREF(o);
3497 if (PyModule_AddObject(m, "TclError", o)) {
3498 Py_DECREF(o);
3499 Py_DECREF(m);
3500 return NULL;
3501 }
3502 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003503
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003504 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3505 Py_DECREF(m);
3506 return NULL;
3507 }
3508 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3509 Py_DECREF(m);
3510 return NULL;
3511 }
3512 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3513 Py_DECREF(m);
3514 return NULL;
3515 }
3516 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3517 Py_DECREF(m);
3518 return NULL;
3519 }
3520 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3521 Py_DECREF(m);
3522 return NULL;
3523 }
3524 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3525 Py_DECREF(m);
3526 return NULL;
3527 }
3528 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3529 Py_DECREF(m);
3530 return NULL;
3531 }
3532 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3533 Py_DECREF(m);
3534 return NULL;
3535 }
3536 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3537 Py_DECREF(m);
3538 return NULL;
3539 }
3540 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3541 Py_DECREF(m);
3542 return NULL;
3543 }
3544 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3545 Py_DECREF(m);
3546 return NULL;
3547 }
3548
3549 o = PyType_FromSpec(&Tkapp_Type_spec);
3550 if (o == NULL) {
3551 Py_DECREF(m);
3552 return NULL;
3553 }
3554 if (PyModule_AddObject(m, "TkappType", o)) {
3555 Py_DECREF(o);
3556 Py_DECREF(m);
3557 return NULL;
3558 }
3559 Tkapp_Type = o;
3560
3561 o = PyType_FromSpec(&Tktt_Type_spec);
3562 if (o == NULL) {
3563 Py_DECREF(m);
3564 return NULL;
3565 }
3566 if (PyModule_AddObject(m, "TkttType", o)) {
3567 Py_DECREF(o);
3568 Py_DECREF(m);
3569 return NULL;
3570 }
3571 Tktt_Type = o;
3572
3573 o = PyType_FromSpec(&PyTclObject_Type_spec);
3574 if (o == NULL) {
3575 Py_DECREF(m);
3576 return NULL;
3577 }
3578 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3579 Py_DECREF(o);
3580 Py_DECREF(m);
3581 return NULL;
3582 }
3583 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003584
3585#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003586 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3587 * start waking up. Note that Tcl_FindExecutable will do this, this
3588 * code must be above it! The original warning from
3589 * tkMacOSXAppInit.c is copied below.
3590 *
3591 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3592 * Tcl interpreter for now. It probably should work to do this
3593 * in the other order, but for now it doesn't seem to.
3594 *
3595 */
3596 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003597#endif
3598
3599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003600 /* This helps the dynamic loader; in Unicode aware Tcl versions
3601 it also helps Tcl find its encodings. */
3602 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3603 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003604 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003605 if (cexe) {
3606#ifdef MS_WINDOWS
3607 int set_var = 0;
3608 PyObject *str_path;
3609 wchar_t *wcs_path;
3610 DWORD ret;
3611
3612 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3613
3614 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3615 str_path = _get_tcl_lib_path();
3616 if (str_path == NULL && PyErr_Occurred()) {
3617 return NULL;
3618 }
3619 if (str_path != NULL) {
3620 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3621 if (wcs_path == NULL) {
3622 return NULL;
3623 }
3624 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3625 set_var = 1;
3626 }
3627 }
3628
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003629 Tcl_FindExecutable(PyBytes_AsString(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003630
3631 if (set_var) {
3632 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3633 PyMem_Free(wcs_path);
3634 }
3635#else
3636 Tcl_FindExecutable(PyBytes_AsString(cexe));
3637#endif /* MS_WINDOWS */
3638 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003639 Py_XDECREF(cexe);
3640 Py_DECREF(uexe);
3641 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003643 if (PyErr_Occurred()) {
3644 Py_DECREF(m);
3645 return NULL;
3646 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003647
Guido van Rossum43ff8681998-07-14 18:02:13 +00003648#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003649 /* This was not a good idea; through <Destroy> bindings,
3650 Tcl_Finalize() may invoke Python code but at that point the
3651 interpreter and thread state have already been destroyed! */
3652 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003653#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003654 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003655}