blob: c4e6b95a7dd4734ded1b2a85d308859196ccacf3 [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
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002488 name: str
2489 func: object
2490 /
2491
2492[clinic start generated code]*/
2493
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002494static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002495_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2496 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002497/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002498{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002499 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002500 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002501
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002502 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002503 if (!PyCallable_Check(func)) {
2504 PyErr_SetString(PyExc_TypeError, "command not callable");
2505 return NULL;
2506 }
Guido van Rossum18468821994-06-20 07:49:28 +00002507
Martin v. Löwisa9656492003-03-30 08:44:58 +00002508#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002509 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2510 !WaitForMainloop(self))
2511 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002512#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002513
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002514 data = PyMem_NEW(PythonCmd_ClientData, 1);
2515 if (!data)
2516 return PyErr_NoMemory();
2517 Py_INCREF(self);
2518 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002519 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002520 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002521#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002522 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2523 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002524 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2525 if (ev == NULL) {
2526 PyErr_NoMemory();
2527 PyMem_DEL(data);
2528 return NULL;
2529 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002530 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2531 ev->interp = self->interp;
2532 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002533 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002534 ev->data = (ClientData)data;
2535 ev->status = &err;
2536 ev->done = &cond;
2537 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2538 Tcl_ConditionFinalize(&cond);
2539 }
2540 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002541#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002542 {
2543 ENTER_TCL
2544 err = Tcl_CreateCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002545 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002546 (ClientData)data, PythonCmdDelete) == NULL;
2547 LEAVE_TCL
2548 }
2549 if (err) {
2550 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2551 PyMem_DEL(data);
2552 return NULL;
2553 }
Guido van Rossum18468821994-06-20 07:49:28 +00002554
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002555 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002556}
2557
Barry Warsawfa701a81997-01-16 00:15:11 +00002558
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002559
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002560/*[clinic input]
2561_tkinter.tkapp.deletecommand
2562
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002563 name: str
2564 /
2565
2566[clinic start generated code]*/
2567
Guido van Rossum18468821994-06-20 07:49:28 +00002568static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002569_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002570/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002571{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002572 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002573
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002574 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002575
2576#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002577 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2578 Tcl_Condition cond = NULL;
2579 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002580 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2581 if (ev == NULL) {
2582 PyErr_NoMemory();
2583 return NULL;
2584 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002585 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2586 ev->interp = self->interp;
2587 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002588 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002589 ev->status = &err;
2590 ev->done = &cond;
2591 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2592 &command_mutex);
2593 Tcl_ConditionFinalize(&cond);
2594 }
2595 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002596#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002597 {
2598 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002599 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002600 LEAVE_TCL
2601 }
2602 if (err == -1) {
2603 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2604 return NULL;
2605 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002606 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002607}
2608
Barry Warsawfa701a81997-01-16 00:15:11 +00002609
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002610
Guido van Rossum00d93061998-05-28 23:06:38 +00002611#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002612/** File Handler **/
2613
Guido van Rossum00d93061998-05-28 23:06:38 +00002614typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002615 PyObject *func;
2616 PyObject *file;
2617 int id;
2618 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002619} FileHandler_ClientData;
2620
2621static FileHandler_ClientData *HeadFHCD;
2622
2623static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002624NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002625{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002626 FileHandler_ClientData *p;
2627 p = PyMem_NEW(FileHandler_ClientData, 1);
2628 if (p != NULL) {
2629 Py_XINCREF(func);
2630 Py_XINCREF(file);
2631 p->func = func;
2632 p->file = file;
2633 p->id = id;
2634 p->next = HeadFHCD;
2635 HeadFHCD = p;
2636 }
2637 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002638}
2639
2640static void
Fred Drake509d79a2000-07-08 04:04:38 +00002641DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002642{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002643 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002645 pp = &HeadFHCD;
2646 while ((p = *pp) != NULL) {
2647 if (p->id == id) {
2648 *pp = p->next;
2649 Py_XDECREF(p->func);
2650 Py_XDECREF(p->file);
2651 PyMem_DEL(p);
2652 }
2653 else
2654 pp = &p->next;
2655 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002656}
2657
Guido van Rossuma597dde1995-01-10 20:56:29 +00002658static void
Fred Drake509d79a2000-07-08 04:04:38 +00002659FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002660{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002661 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2662 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002664 ENTER_PYTHON
2665 func = data->func;
2666 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002668 arg = Py_BuildValue("(Oi)", file, (long) mask);
2669 res = PyEval_CallObject(func, arg);
2670 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002672 if (res == NULL) {
2673 errorInCmd = 1;
2674 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2675 }
2676 Py_XDECREF(res);
2677 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002678}
2679
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002680/*[clinic input]
2681_tkinter.tkapp.createfilehandler
2682
2683 file: object
2684 mask: int
2685 func: object
2686 /
2687
2688[clinic start generated code]*/
2689
Guido van Rossum18468821994-06-20 07:49:28 +00002690static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002691_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2692 int mask, PyObject *func)
2693/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002694{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002695 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002696 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002697
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002698 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002700 tfile = PyObject_AsFileDescriptor(file);
2701 if (tfile < 0)
2702 return NULL;
2703 if (!PyCallable_Check(func)) {
2704 PyErr_SetString(PyExc_TypeError, "bad argument list");
2705 return NULL;
2706 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002707
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002708 data = NewFHCD(func, file, tfile);
2709 if (data == NULL)
2710 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002711
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002712 /* Ought to check for null Tcl_File object... */
2713 ENTER_TCL
2714 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2715 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002716 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002717}
2718
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002719/*[clinic input]
2720_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002721
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002722 file: object
2723 /
2724
2725[clinic start generated code]*/
2726
2727static PyObject *
2728_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2729/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2730{
2731 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002732
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002733 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002734
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002735 tfile = PyObject_AsFileDescriptor(file);
2736 if (tfile < 0)
2737 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002738
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002739 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741 /* Ought to check for null Tcl_File object... */
2742 ENTER_TCL
2743 Tcl_DeleteFileHandler(tfile);
2744 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002745 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002746}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002747#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002749
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002750/**** Tktt Object (timer token) ****/
2751
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002752static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002753
Guido van Rossum00d93061998-05-28 23:06:38 +00002754typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002755 PyObject_HEAD
2756 Tcl_TimerToken token;
2757 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002758} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002759
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002760/*[clinic input]
2761_tkinter.tktimertoken.deletetimerhandler
2762
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002763[clinic start generated code]*/
2764
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002765static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002766_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002767/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002768{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002769 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002770 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002771
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002772 if (v->token != NULL) {
2773 Tcl_DeleteTimerHandler(v->token);
2774 v->token = NULL;
2775 }
2776 if (func != NULL) {
2777 v->func = NULL;
2778 Py_DECREF(func);
2779 Py_DECREF(v); /* See Tktt_New() */
2780 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002781 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002782}
2783
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002784static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002785Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002786{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002787 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002788
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002789 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002790 if (v == NULL)
2791 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002792 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002793
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 Py_INCREF(func);
2795 v->token = NULL;
2796 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002798 /* Extra reference, deleted when called or when handler is deleted */
2799 Py_INCREF(v);
2800 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002801}
2802
2803static void
Fred Drake509d79a2000-07-08 04:04:38 +00002804Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002805{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002806 TkttObject *v = (TkttObject *)self;
2807 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002808 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002809
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002810 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002811
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002812 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002813 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002814}
2815
Guido van Rossum597ac201998-05-12 14:36:19 +00002816static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002817Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002818{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002819 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002820 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2821 v,
2822 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002823}
2824
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002825/** Timer Handler **/
2826
2827static void
Fred Drake509d79a2000-07-08 04:04:38 +00002828TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002829{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002830 TkttObject *v = (TkttObject *)clientData;
2831 PyObject *func = v->func;
2832 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002833
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002834 if (func == NULL)
2835 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002837 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002838
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002839 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002840
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002841 res = PyEval_CallObject(func, NULL);
2842 Py_DECREF(func);
2843 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002844
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002845 if (res == NULL) {
2846 errorInCmd = 1;
2847 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2848 }
2849 else
2850 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002851
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002852 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002853}
2854
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002855/*[clinic input]
2856_tkinter.tkapp.createtimerhandler
2857
2858 milliseconds: int
2859 func: object
2860 /
2861
2862[clinic start generated code]*/
2863
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002864static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002865_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2866 PyObject *func)
2867/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002868{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002869 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002870
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002871 if (!PyCallable_Check(func)) {
2872 PyErr_SetString(PyExc_TypeError, "bad argument list");
2873 return NULL;
2874 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002876 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002877
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002878 v = Tktt_New(func);
2879 if (v) {
2880 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2881 (ClientData)v);
2882 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002883
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002884 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002885}
2886
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002887
Guido van Rossum18468821994-06-20 07:49:28 +00002888/** Event Loop **/
2889
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002890/*[clinic input]
2891_tkinter.tkapp.mainloop
2892
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002893 threshold: int = 0
2894 /
2895
2896[clinic start generated code]*/
2897
Guido van Rossum18468821994-06-20 07:49:28 +00002898static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002899_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002900/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002901{
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002902#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002903 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002904#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002905
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002906 CHECK_TCL_APPARTMENT;
2907 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002908
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002909 quitMainLoop = 0;
2910 while (Tk_GetNumMainWindows() > threshold &&
2911 !quitMainLoop &&
2912 !errorInCmd)
2913 {
2914 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002915
2916#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002917 if (self->threaded) {
2918 /* Allow other Python threads to run. */
2919 ENTER_TCL
2920 result = Tcl_DoOneEvent(0);
2921 LEAVE_TCL
2922 }
2923 else {
2924 Py_BEGIN_ALLOW_THREADS
2925 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2926 tcl_tstate = tstate;
2927 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2928 tcl_tstate = NULL;
2929 if(tcl_lock)PyThread_release_lock(tcl_lock);
2930 if (result == 0)
2931 Sleep(Tkinter_busywaitinterval);
2932 Py_END_ALLOW_THREADS
2933 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002934#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002935 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002936#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002937
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002938 if (PyErr_CheckSignals() != 0) {
2939 self->dispatching = 0;
2940 return NULL;
2941 }
2942 if (result < 0)
2943 break;
2944 }
2945 self->dispatching = 0;
2946 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002947
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002948 if (errorInCmd) {
2949 errorInCmd = 0;
2950 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2951 excInCmd = valInCmd = trbInCmd = NULL;
2952 return NULL;
2953 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002954 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002955}
2956
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002957/*[clinic input]
2958_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002959
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002960 flags: int = 0
2961 /
2962
2963[clinic start generated code]*/
2964
2965static PyObject *
2966_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2967/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2968{
2969 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002970
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002971 ENTER_TCL
2972 rv = Tcl_DoOneEvent(flags);
2973 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002974 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002975}
2976
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002977/*[clinic input]
2978_tkinter.tkapp.quit
2979[clinic start generated code]*/
2980
Guido van Rossum062cfb01995-01-10 17:42:51 +00002981static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002982_tkinter_tkapp_quit_impl(TkappObject *self)
2983/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002984{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002985 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002986 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002987}
2988
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002989/*[clinic input]
2990_tkinter.tkapp.interpaddr
2991[clinic start generated code]*/
2992
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002993static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002994_tkinter_tkapp_interpaddr_impl(TkappObject *self)
2995/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002996{
Victor Stinnere1040e22013-09-05 00:22:24 +02002997 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002998}
2999
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003000/*[clinic input]
3001_tkinter.tkapp.loadtk
3002[clinic start generated code]*/
3003
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003004static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003005_tkinter_tkapp_loadtk_impl(TkappObject *self)
3006/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00003007{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003008 Tcl_Interp *interp = Tkapp_Interp(self);
3009 const char * _tk_exists = NULL;
3010 int err;
David Aschere2b4b322004-02-18 05:59:53 +00003011
Guilherme Polob681df42009-02-09 22:33:59 +00003012#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003013 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
3014 * first call failed.
3015 * To avoid the deadlock, we just refuse the second call through
3016 * a static variable.
3017 */
3018 if (tk_load_failed) {
3019 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
3020 return NULL;
3021 }
Guilherme Polob681df42009-02-09 22:33:59 +00003022#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003023
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003024 /* We want to guard against calling Tk_Init() multiple times */
3025 CHECK_TCL_APPARTMENT;
3026 ENTER_TCL
3027 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
3028 ENTER_OVERLAP
3029 if (err == TCL_ERROR) {
3030 /* This sets an exception, but we cannot return right
3031 away because we need to exit the overlap first. */
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003032 Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003033 } else {
3034 _tk_exists = Tkapp_Result(self);
3035 }
3036 LEAVE_OVERLAP_TCL
3037 if (err == TCL_ERROR) {
3038 return NULL;
3039 }
3040 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
3041 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003042 PyErr_SetString(Tkinter_TclError,
3043 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00003044#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003045 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00003046#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003047 return NULL;
3048 }
3049 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003050 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00003051}
Barry Warsawfa701a81997-01-16 00:15:11 +00003052
Martin v. Löwisffad6332002-11-26 09:28:05 +00003053static PyObject *
3054Tkapp_WantObjects(PyObject *self, PyObject *args)
3055{
3056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003057 int wantobjects = -1;
3058 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3059 return NULL;
3060 if (wantobjects == -1)
3061 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3062 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003063
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003064 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003065}
3066
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003067/*[clinic input]
3068_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003069
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003070[clinic start generated code]*/
3071
3072static PyObject *
3073_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03003074/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003075{
3076 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003077
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003078 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003079}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003080
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003081
Guido van Rossum18468821994-06-20 07:49:28 +00003082/**** Tkapp Type Methods ****/
3083
3084static void
Fred Drake509d79a2000-07-08 04:04:38 +00003085Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003086{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003087 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003088 /*CHECK_TCL_APPARTMENT;*/
3089 ENTER_TCL
3090 Tcl_DeleteInterp(Tkapp_Interp(self));
3091 LEAVE_TCL
3092 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003093 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003094 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003095}
3096
Barry Warsawfa701a81997-01-16 00:15:11 +00003097
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003098
Guido van Rossum18468821994-06-20 07:49:28 +00003099/**** Tkinter Module ****/
3100
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003101typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003102 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003103 Py_ssize_t size; /* current size */
3104 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003105} FlattenContext;
3106
3107static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003108_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003109{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003110 /* expand tuple to hold (at least) size new items.
3111 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003112
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003113 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003114
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003115 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003116 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003118 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003119
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003120 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003121}
3122
3123static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003124_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003125{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003126 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003127
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003128 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003129
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003130 if (depth > 1000) {
3131 PyErr_SetString(PyExc_ValueError,
3132 "nesting too deep in _flatten");
3133 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003134 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3135 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003136 /* preallocate (assume no nesting) */
3137 if (context->size + size > context->maxsize &&
3138 !_bump(context, size))
3139 return 0;
3140 /* copy items to output tuple */
3141 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003142 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003143 if (PyList_Check(o) || PyTuple_Check(o)) {
3144 if (!_flatten1(context, o, depth + 1))
3145 return 0;
3146 } else if (o != Py_None) {
3147 if (context->size + 1 > context->maxsize &&
3148 !_bump(context, 1))
3149 return 0;
3150 Py_INCREF(o);
3151 PyTuple_SET_ITEM(context->tuple,
3152 context->size++, o);
3153 }
3154 }
3155 } else {
3156 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3157 return 0;
3158 }
3159 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003160}
3161
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003162/*[clinic input]
3163_tkinter._flatten
3164
3165 item: object
3166 /
3167
3168[clinic start generated code]*/
3169
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003170static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003171_tkinter__flatten(PyModuleDef *module, PyObject *item)
3172/*[clinic end generated code: output=9505049ec74c3480 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003173{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003174 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003175
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003176 context.maxsize = PySequence_Size(item);
3177 if (context.maxsize < 0)
3178 return NULL;
3179 if (context.maxsize == 0)
3180 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003181
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003182 context.tuple = PyTuple_New(context.maxsize);
3183 if (!context.tuple)
3184 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003185
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003186 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003187
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003188 if (!_flatten1(&context, item,0))
3189 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003190
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003191 if (_PyTuple_Resize(&context.tuple, context.size))
3192 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003193
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003194 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003195}
3196
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003197/*[clinic input]
3198_tkinter.create
3199
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003200 screenName: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003201 baseName: str = NULL
3202 className: str = "Tk"
3203 interactive: int(c_default="0") = False
3204 wantobjects: int(c_default="0") = False
3205 wantTk: int(c_default="1") = True
3206 if false, then Tk_Init() doesn't get called
3207 sync: int(c_default="0") = False
3208 if true, then pass -sync to wish
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003209 use: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003210 if not None, then pass -use to wish
3211 /
3212
3213[clinic start generated code]*/
3214
Guido van Rossum18468821994-06-20 07:49:28 +00003215static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003216_tkinter_create_impl(PyModuleDef *module, const char *screenName,
3217 const char *baseName, const char *className,
3218 int interactive, int wantobjects, int wantTk, int sync,
3219 const char *use)
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003220/*[clinic end generated code: output=b8847800fc3b27eb input=0d522aad1cb0ca0e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003221{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003222 /* XXX baseName is not used anymore;
3223 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003224 CHECK_STRING_LENGTH(screenName);
3225 CHECK_STRING_LENGTH(baseName);
3226 CHECK_STRING_LENGTH(className);
3227 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003228
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003229 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003230 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003231 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003232}
3233
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003234/*[clinic input]
3235_tkinter.setbusywaitinterval
3236
3237 new_val: int
3238 /
3239
3240Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3241
3242It should be set to a divisor of the maximum time between frames in an animation.
3243[clinic start generated code]*/
3244
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003245static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003246_tkinter_setbusywaitinterval_impl(PyModuleDef *module, int new_val)
3247/*[clinic end generated code: output=0b9d7ef7940461ea input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003248{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003249 if (new_val < 0) {
3250 PyErr_SetString(PyExc_ValueError,
3251 "busywaitinterval must be >= 0");
3252 return NULL;
3253 }
3254 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003255 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003256}
3257
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003258/*[clinic input]
3259_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003260
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003261Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3262[clinic start generated code]*/
3263
3264static int
3265_tkinter_getbusywaitinterval_impl(PyModuleDef *module)
3266/*[clinic end generated code: output=9d09eee026e96971 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003267{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003268 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003269}
3270
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003271#include "clinic/_tkinter.c.h"
3272
3273static PyMethodDef Tktt_methods[] =
3274{
3275 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3276 {NULL, NULL}
3277};
3278
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003279static PyType_Slot Tktt_Type_slots[] = {
3280 {Py_tp_dealloc, Tktt_Dealloc},
3281 {Py_tp_repr, Tktt_Repr},
3282 {Py_tp_methods, Tktt_methods},
3283 {0, 0}
3284};
3285
3286static PyType_Spec Tktt_Type_spec = {
3287 "_tkinter.tktimertoken",
3288 sizeof(TkttObject),
3289 0,
3290 Py_TPFLAGS_DEFAULT,
3291 Tktt_Type_slots,
3292};
3293
3294
3295/**** Tkapp Method List ****/
3296
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003297static PyMethodDef Tkapp_methods[] =
3298{
3299 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3300 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3301 {"call", Tkapp_Call, METH_VARARGS},
3302 _TKINTER_TKAPP_EVAL_METHODDEF
3303 _TKINTER_TKAPP_EVALFILE_METHODDEF
3304 _TKINTER_TKAPP_RECORD_METHODDEF
3305 _TKINTER_TKAPP_ADDERRINFO_METHODDEF
3306 {"setvar", Tkapp_SetVar, METH_VARARGS},
3307 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3308 {"getvar", Tkapp_GetVar, METH_VARARGS},
3309 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3310 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3311 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3312 _TKINTER_TKAPP_GETINT_METHODDEF
3313 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3314 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3315 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3316 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3317 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3318 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3319 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3320 _TKINTER_TKAPP_SPLIT_METHODDEF
3321 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3322 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3323 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3324 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3325 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3326 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3327 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3328 _TKINTER_TKAPP_QUIT_METHODDEF
3329 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3330 _TKINTER_TKAPP_LOADTK_METHODDEF
3331 {NULL, NULL}
3332};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003333
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003334static PyType_Slot Tkapp_Type_slots[] = {
3335 {Py_tp_dealloc, Tkapp_Dealloc},
3336 {Py_tp_methods, Tkapp_methods},
3337 {0, 0}
3338};
3339
3340
3341static PyType_Spec Tkapp_Type_spec = {
3342 "_tkinter.tkapp",
3343 sizeof(TkappObject),
3344 0,
3345 Py_TPFLAGS_DEFAULT,
3346 Tkapp_Type_slots,
3347};
3348
Guido van Rossum18468821994-06-20 07:49:28 +00003349static PyMethodDef moduleMethods[] =
3350{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003351 _TKINTER__FLATTEN_METHODDEF
3352 _TKINTER_CREATE_METHODDEF
3353 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3354 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003355 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003356};
3357
Guido van Rossum7bf15641998-05-22 18:28:17 +00003358#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003359
3360static int stdin_ready = 0;
3361
Guido van Rossumad4db171998-06-13 13:56:28 +00003362#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003363static void
Fred Drake509d79a2000-07-08 04:04:38 +00003364MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003365{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003366 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003367}
Guido van Rossumad4db171998-06-13 13:56:28 +00003368#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003369
Martin v. Löwisa9656492003-03-30 08:44:58 +00003370#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003371static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003372#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003373
Guido van Rossum18468821994-06-20 07:49:28 +00003374static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003375EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003376{
Guido van Rossumad4db171998-06-13 13:56:28 +00003377#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003378 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003379#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003380#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003381 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003382#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003383 stdin_ready = 0;
3384 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003385#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003386 tfile = fileno(stdin);
3387 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003388#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003389 while (!errorInCmd && !stdin_ready) {
3390 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003391#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003392 if (_kbhit()) {
3393 stdin_ready = 1;
3394 break;
3395 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003396#endif
3397#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003398 Py_BEGIN_ALLOW_THREADS
3399 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3400 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003401
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003402 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003403
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003404 tcl_tstate = NULL;
3405 if(tcl_lock)PyThread_release_lock(tcl_lock);
3406 if (result == 0)
3407 Sleep(Tkinter_busywaitinterval);
3408 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003409#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003410 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003411#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003413 if (result < 0)
3414 break;
3415 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003416#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003417 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003418#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003419 if (errorInCmd) {
3420 errorInCmd = 0;
3421 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3422 excInCmd = valInCmd = trbInCmd = NULL;
3423 PyErr_Print();
3424 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003425#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003426 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003427#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003428 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003429}
Guido van Rossum18468821994-06-20 07:49:28 +00003430
Guido van Rossum00d93061998-05-28 23:06:38 +00003431#endif
3432
Guido van Rossum7bf15641998-05-22 18:28:17 +00003433static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003434EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003435{
Guido van Rossum00d93061998-05-28 23:06:38 +00003436#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003437 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003438#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003439 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003440#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003441 PyOS_InputHook = EventHook;
3442 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003443#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003444}
3445
3446static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003447DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003448{
Guido van Rossum00d93061998-05-28 23:06:38 +00003449#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003450 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3451 PyOS_InputHook = NULL;
3452 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003453#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003454}
3455
Barry Warsawfa701a81997-01-16 00:15:11 +00003456
Martin v. Löwis1a214512008-06-11 05:26:20 +00003457static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003458 PyModuleDef_HEAD_INIT,
3459 "_tkinter",
3460 NULL,
3461 -1,
3462 moduleMethods,
3463 NULL,
3464 NULL,
3465 NULL,
3466 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003467};
3468
Mark Hammond62b1ab12002-07-23 06:31:15 +00003469PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003470PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003471{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003472 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003473
Guido van Rossum00d93061998-05-28 23:06:38 +00003474#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003475 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003476 if (tcl_lock == NULL)
3477 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003478#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003480 m = PyModule_Create(&_tkintermodule);
3481 if (m == NULL)
3482 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003483
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003484 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3485 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003486 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003487 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003488 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003489 Py_INCREF(o);
3490 if (PyModule_AddObject(m, "TclError", o)) {
3491 Py_DECREF(o);
3492 Py_DECREF(m);
3493 return NULL;
3494 }
3495 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003496
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003497 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3498 Py_DECREF(m);
3499 return NULL;
3500 }
3501 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3502 Py_DECREF(m);
3503 return NULL;
3504 }
3505 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3506 Py_DECREF(m);
3507 return NULL;
3508 }
3509 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3510 Py_DECREF(m);
3511 return NULL;
3512 }
3513 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3514 Py_DECREF(m);
3515 return NULL;
3516 }
3517 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3518 Py_DECREF(m);
3519 return NULL;
3520 }
3521 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3522 Py_DECREF(m);
3523 return NULL;
3524 }
3525 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3526 Py_DECREF(m);
3527 return NULL;
3528 }
3529 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3530 Py_DECREF(m);
3531 return NULL;
3532 }
3533 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3534 Py_DECREF(m);
3535 return NULL;
3536 }
3537 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3538 Py_DECREF(m);
3539 return NULL;
3540 }
3541
3542 o = PyType_FromSpec(&Tkapp_Type_spec);
3543 if (o == NULL) {
3544 Py_DECREF(m);
3545 return NULL;
3546 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003547 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003548 if (PyModule_AddObject(m, "TkappType", o)) {
3549 Py_DECREF(o);
3550 Py_DECREF(m);
3551 return NULL;
3552 }
3553 Tkapp_Type = o;
3554
3555 o = PyType_FromSpec(&Tktt_Type_spec);
3556 if (o == NULL) {
3557 Py_DECREF(m);
3558 return NULL;
3559 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003560 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003561 if (PyModule_AddObject(m, "TkttType", o)) {
3562 Py_DECREF(o);
3563 Py_DECREF(m);
3564 return NULL;
3565 }
3566 Tktt_Type = o;
3567
3568 o = PyType_FromSpec(&PyTclObject_Type_spec);
3569 if (o == NULL) {
3570 Py_DECREF(m);
3571 return NULL;
3572 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003573 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003574 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3575 Py_DECREF(o);
3576 Py_DECREF(m);
3577 return NULL;
3578 }
3579 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003580
3581#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003582 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3583 * start waking up. Note that Tcl_FindExecutable will do this, this
3584 * code must be above it! The original warning from
3585 * tkMacOSXAppInit.c is copied below.
3586 *
3587 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3588 * Tcl interpreter for now. It probably should work to do this
3589 * in the other order, but for now it doesn't seem to.
3590 *
3591 */
3592 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003593#endif
3594
3595
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003596 /* This helps the dynamic loader; in Unicode aware Tcl versions
3597 it also helps Tcl find its encodings. */
3598 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3599 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003600 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003601 if (cexe) {
3602#ifdef MS_WINDOWS
3603 int set_var = 0;
3604 PyObject *str_path;
3605 wchar_t *wcs_path;
3606 DWORD ret;
3607
3608 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3609
3610 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3611 str_path = _get_tcl_lib_path();
3612 if (str_path == NULL && PyErr_Occurred()) {
3613 return NULL;
3614 }
3615 if (str_path != NULL) {
3616 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3617 if (wcs_path == NULL) {
3618 return NULL;
3619 }
3620 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3621 set_var = 1;
3622 }
3623 }
3624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003625 Tcl_FindExecutable(PyBytes_AsString(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003626
3627 if (set_var) {
3628 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3629 PyMem_Free(wcs_path);
3630 }
3631#else
3632 Tcl_FindExecutable(PyBytes_AsString(cexe));
3633#endif /* MS_WINDOWS */
3634 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003635 Py_XDECREF(cexe);
3636 Py_DECREF(uexe);
3637 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003638
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003639 if (PyErr_Occurred()) {
3640 Py_DECREF(m);
3641 return NULL;
3642 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003643
Guido van Rossum43ff8681998-07-14 18:02:13 +00003644#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003645 /* This was not a good idea; through <Destroy> bindings,
3646 Tcl_Finalize() may invoke Python code but at that point the
3647 interpreter and thread state have already been destroyed! */
3648 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003649#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003650 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003651}