blob: 761ec0db8ff65eb4291e8eff761a1b1dde601ca8 [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 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300465 PyTuple_SET_ITEM(v, i, w);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 }
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
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300483 size = PyTuple_GET_SIZE(arg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000484 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++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300489 elem = PyTuple_GET_ITEM(arg, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 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++) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300505 elem = PyTuple_GET_ITEM(arg, k);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000506 Py_INCREF(elem);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300507 PyTuple_SET_ITEM(result, k, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000508 }
509 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300510 PyTuple_SET_ITEM(result, i, newelem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000511 }
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 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300532 PyTuple_SET_ITEM(result, i, newelem);
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300533 }
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;
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300554 char *list = PyBytes_AS_STRING(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)
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300562 return Split(PyBytes_AS_STRING(arg));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000563 /* 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",
Serhiy Storchaka696c8af2016-06-19 11:22:47 +0300761 PyBytes_AS_STRING(utf8_path),
Zachary Ware7dc9dea2015-05-22 11:36:53 -0500762 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 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001309 PyTuple_SET_ITEM(result, i, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001310 }
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 */
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001520 if (PyTuple_GET_SIZE(args) == 1) {
1521 PyObject *item = PyTuple_GET_ITEM(args, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001522 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 Storchaka696c8af2016-06-19 11:22:47 +03001731 if (PyBytes_GET_SIZE(in) > INT_MAX) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001732 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1733 return 0;
1734 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001735 s = PyBytes_AS_STRING(in);
1736 if (strlen(s) != (size_t)PyBytes_GET_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 Storchaka696c8af2016-06-19 11:22:47 +03002277 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002278 Py_DECREF(v);
2279 return NULL;
2280 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002281 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002282 }
2283 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002284 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002285 if (PyTuple_Check(arg)) {
2286 Py_INCREF(arg);
2287 return arg;
2288 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002289 if (PyList_Check(arg)) {
2290 return PySequence_Tuple(arg);
2291 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002292
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002293 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002294 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002295
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002296 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002297 if (Tcl_SplitList(Tkapp_Interp(self), list,
2298 &argc, &argv) == TCL_ERROR) {
2299 PyMem_Free(list);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002300 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002301 }
Guido van Rossum18468821994-06-20 07:49:28 +00002302
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002303 if (!(v = PyTuple_New(argc)))
2304 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002305
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002306 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002307 PyObject *s = unicodeFromTclString(argv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002308 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002309 Py_DECREF(v);
2310 v = NULL;
2311 goto finally;
2312 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002313 PyTuple_SET_ITEM(v, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002314 }
Guido van Rossum18468821994-06-20 07:49:28 +00002315
Barry Warsawfa701a81997-01-16 00:15:11 +00002316 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002317 ckfree(FREECAST argv);
2318 PyMem_Free(list);
2319 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002320}
2321
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002322/*[clinic input]
2323_tkinter.tkapp.split
2324
2325 arg: object
2326 /
2327
2328[clinic start generated code]*/
2329
Guido van Rossum18468821994-06-20 07:49:28 +00002330static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002331_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2332/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002333{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002334 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002335 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002336
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002337 if (PyTclObject_Check(arg)) {
2338 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2339 int objc;
2340 Tcl_Obj **objv;
2341 int i;
2342 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2343 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002344 return FromObj((PyObject*)self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002345 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002346 if (objc == 0)
2347 return PyUnicode_FromString("");
2348 if (objc == 1)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002349 return FromObj((PyObject*)self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002350 if (!(v = PyTuple_New(objc)))
2351 return NULL;
2352 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002353 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002354 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002355 Py_DECREF(v);
2356 return NULL;
2357 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002358 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002359 }
2360 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002361 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002362 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002363 return SplitObj(arg);
2364
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002365 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002366 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002367 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002368 v = Split(list);
2369 PyMem_Free(list);
2370 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002371}
2372
Barry Warsawfa701a81997-01-16 00:15:11 +00002373
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002374
Guido van Rossum18468821994-06-20 07:49:28 +00002375/** Tcl Command **/
2376
Guido van Rossum00d93061998-05-28 23:06:38 +00002377/* Client data struct */
2378typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002379 PyObject *self;
2380 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002381} PythonCmd_ClientData;
2382
2383static int
Fred Drake509d79a2000-07-08 04:04:38 +00002384PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002385{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002386 errorInCmd = 1;
2387 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2388 LEAVE_PYTHON
2389 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002390}
2391
Guido van Rossum18468821994-06-20 07:49:28 +00002392/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002393 * function or method.
2394 */
Guido van Rossum18468821994-06-20 07:49:28 +00002395static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002396PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002397{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002398 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002399 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002400 int i, rv;
2401 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002403 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002405 /* TBD: no error checking here since we know, via the
2406 * Tkapp_CreateCommand() that the client data is a two-tuple
2407 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002408 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002409
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002410 /* Create argument list (argv1, ..., argvN) */
2411 if (!(arg = PyTuple_New(argc - 1)))
2412 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002413
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002414 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002415 PyObject *s = unicodeFromTclString(argv[i + 1]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002416 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002417 Py_DECREF(arg);
2418 return PythonCmd_Error(interp);
2419 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002420 PyTuple_SET_ITEM(arg, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002421 }
2422 res = PyEval_CallObject(func, arg);
2423 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002424
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002425 if (res == NULL)
2426 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002427
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002428 obj_res = AsObj(res);
2429 if (obj_res == NULL) {
2430 Py_DECREF(res);
2431 return PythonCmd_Error(interp);
2432 }
2433 else {
2434 Tcl_SetObjResult(interp, obj_res);
2435 rv = TCL_OK;
2436 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002438 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002439
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002440 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002441
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002442 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002443}
2444
2445static void
Fred Drake509d79a2000-07-08 04:04:38 +00002446PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002447{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002448 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002449
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002450 ENTER_PYTHON
2451 Py_XDECREF(data->self);
2452 Py_XDECREF(data->func);
2453 PyMem_DEL(data);
2454 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002455}
2456
Barry Warsawfa701a81997-01-16 00:15:11 +00002457
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002458
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002459
Benjamin Peterson5879d412009-03-30 14:51:56 +00002460#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002461TCL_DECLARE_MUTEX(command_mutex)
2462
2463typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002464 Tcl_Event ev;
2465 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002466 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002467 int create;
2468 int *status;
2469 ClientData *data;
2470 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002471} CommandEvent;
2472
2473static int
2474Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002475{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002476 if (ev->create)
2477 *ev->status = Tcl_CreateCommand(
2478 ev->interp, ev->name, PythonCmd,
2479 ev->data, PythonCmdDelete) == NULL;
2480 else
2481 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2482 Tcl_MutexLock(&command_mutex);
2483 Tcl_ConditionNotify(ev->done);
2484 Tcl_MutexUnlock(&command_mutex);
2485 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002486}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002487#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002488
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002489/*[clinic input]
2490_tkinter.tkapp.createcommand
2491
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002492 name: str
2493 func: object
2494 /
2495
2496[clinic start generated code]*/
2497
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002498static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002499_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2500 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002501/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002502{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002503 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002504 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002505
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002506 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002507 if (!PyCallable_Check(func)) {
2508 PyErr_SetString(PyExc_TypeError, "command not callable");
2509 return NULL;
2510 }
Guido van Rossum18468821994-06-20 07:49:28 +00002511
Martin v. Löwisa9656492003-03-30 08:44:58 +00002512#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002513 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2514 !WaitForMainloop(self))
2515 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002516#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002517
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002518 data = PyMem_NEW(PythonCmd_ClientData, 1);
2519 if (!data)
2520 return PyErr_NoMemory();
2521 Py_INCREF(self);
2522 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002523 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002524 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002525#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002526 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2527 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002528 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2529 if (ev == NULL) {
2530 PyErr_NoMemory();
2531 PyMem_DEL(data);
2532 return NULL;
2533 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002534 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2535 ev->interp = self->interp;
2536 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002537 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002538 ev->data = (ClientData)data;
2539 ev->status = &err;
2540 ev->done = &cond;
2541 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2542 Tcl_ConditionFinalize(&cond);
2543 }
2544 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002545#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002546 {
2547 ENTER_TCL
2548 err = Tcl_CreateCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002549 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002550 (ClientData)data, PythonCmdDelete) == NULL;
2551 LEAVE_TCL
2552 }
2553 if (err) {
2554 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2555 PyMem_DEL(data);
2556 return NULL;
2557 }
Guido van Rossum18468821994-06-20 07:49:28 +00002558
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002559 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002560}
2561
Barry Warsawfa701a81997-01-16 00:15:11 +00002562
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002563
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002564/*[clinic input]
2565_tkinter.tkapp.deletecommand
2566
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002567 name: str
2568 /
2569
2570[clinic start generated code]*/
2571
Guido van Rossum18468821994-06-20 07:49:28 +00002572static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002573_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002574/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002575{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002576 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002577
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002578 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002579
2580#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002581 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2582 Tcl_Condition cond = NULL;
2583 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002584 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2585 if (ev == NULL) {
2586 PyErr_NoMemory();
2587 return NULL;
2588 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002589 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2590 ev->interp = self->interp;
2591 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002592 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002593 ev->status = &err;
2594 ev->done = &cond;
2595 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2596 &command_mutex);
2597 Tcl_ConditionFinalize(&cond);
2598 }
2599 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002600#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002601 {
2602 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002603 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002604 LEAVE_TCL
2605 }
2606 if (err == -1) {
2607 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2608 return NULL;
2609 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002610 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002611}
2612
Barry Warsawfa701a81997-01-16 00:15:11 +00002613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002614
Guido van Rossum00d93061998-05-28 23:06:38 +00002615#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002616/** File Handler **/
2617
Guido van Rossum00d93061998-05-28 23:06:38 +00002618typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002619 PyObject *func;
2620 PyObject *file;
2621 int id;
2622 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002623} FileHandler_ClientData;
2624
2625static FileHandler_ClientData *HeadFHCD;
2626
2627static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002628NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002629{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002630 FileHandler_ClientData *p;
2631 p = PyMem_NEW(FileHandler_ClientData, 1);
2632 if (p != NULL) {
2633 Py_XINCREF(func);
2634 Py_XINCREF(file);
2635 p->func = func;
2636 p->file = file;
2637 p->id = id;
2638 p->next = HeadFHCD;
2639 HeadFHCD = p;
2640 }
2641 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002642}
2643
2644static void
Fred Drake509d79a2000-07-08 04:04:38 +00002645DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002646{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002647 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002648
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002649 pp = &HeadFHCD;
2650 while ((p = *pp) != NULL) {
2651 if (p->id == id) {
2652 *pp = p->next;
2653 Py_XDECREF(p->func);
2654 Py_XDECREF(p->file);
2655 PyMem_DEL(p);
2656 }
2657 else
2658 pp = &p->next;
2659 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002660}
2661
Guido van Rossuma597dde1995-01-10 20:56:29 +00002662static void
Fred Drake509d79a2000-07-08 04:04:38 +00002663FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002664{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002665 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2666 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002668 ENTER_PYTHON
2669 func = data->func;
2670 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002672 arg = Py_BuildValue("(Oi)", file, (long) mask);
2673 res = PyEval_CallObject(func, arg);
2674 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 if (res == NULL) {
2677 errorInCmd = 1;
2678 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2679 }
2680 Py_XDECREF(res);
2681 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002682}
2683
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002684/*[clinic input]
2685_tkinter.tkapp.createfilehandler
2686
2687 file: object
2688 mask: int
2689 func: object
2690 /
2691
2692[clinic start generated code]*/
2693
Guido van Rossum18468821994-06-20 07:49:28 +00002694static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002695_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2696 int mask, PyObject *func)
2697/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002698{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002699 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002700 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002702 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002703
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002704 tfile = PyObject_AsFileDescriptor(file);
2705 if (tfile < 0)
2706 return NULL;
2707 if (!PyCallable_Check(func)) {
2708 PyErr_SetString(PyExc_TypeError, "bad argument list");
2709 return NULL;
2710 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002711
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002712 data = NewFHCD(func, file, tfile);
2713 if (data == NULL)
2714 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002715
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002716 /* Ought to check for null Tcl_File object... */
2717 ENTER_TCL
2718 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2719 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002720 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002721}
2722
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002723/*[clinic input]
2724_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002725
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002726 file: object
2727 /
2728
2729[clinic start generated code]*/
2730
2731static PyObject *
2732_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2733/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2734{
2735 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002736
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002737 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002738
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002739 tfile = PyObject_AsFileDescriptor(file);
2740 if (tfile < 0)
2741 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002743 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002744
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002745 /* Ought to check for null Tcl_File object... */
2746 ENTER_TCL
2747 Tcl_DeleteFileHandler(tfile);
2748 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002749 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002750}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002751#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002752
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002753
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002754/**** Tktt Object (timer token) ****/
2755
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002756static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002757
Guido van Rossum00d93061998-05-28 23:06:38 +00002758typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002759 PyObject_HEAD
2760 Tcl_TimerToken token;
2761 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002762} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002763
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002764/*[clinic input]
2765_tkinter.tktimertoken.deletetimerhandler
2766
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002767[clinic start generated code]*/
2768
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002769static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002770_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002771/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002772{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002773 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002774 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002775
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002776 if (v->token != NULL) {
2777 Tcl_DeleteTimerHandler(v->token);
2778 v->token = NULL;
2779 }
2780 if (func != NULL) {
2781 v->func = NULL;
2782 Py_DECREF(func);
2783 Py_DECREF(v); /* See Tktt_New() */
2784 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002785 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002786}
2787
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002788static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002789Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002790{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002791 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002792
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002793 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 if (v == NULL)
2795 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002796 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002798 Py_INCREF(func);
2799 v->token = NULL;
2800 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002801
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002802 /* Extra reference, deleted when called or when handler is deleted */
2803 Py_INCREF(v);
2804 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002805}
2806
2807static void
Fred Drake509d79a2000-07-08 04:04:38 +00002808Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002809{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002810 TkttObject *v = (TkttObject *)self;
2811 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002812 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002813
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002814 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002815
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002816 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002817 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002818}
2819
Guido van Rossum597ac201998-05-12 14:36:19 +00002820static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002821Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002822{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002823 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002824 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2825 v,
2826 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002827}
2828
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002829/** Timer Handler **/
2830
2831static void
Fred Drake509d79a2000-07-08 04:04:38 +00002832TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002833{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002834 TkttObject *v = (TkttObject *)clientData;
2835 PyObject *func = v->func;
2836 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002837
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002838 if (func == NULL)
2839 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002840
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002841 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002842
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002843 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002844
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002845 res = PyEval_CallObject(func, NULL);
2846 Py_DECREF(func);
2847 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002848
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002849 if (res == NULL) {
2850 errorInCmd = 1;
2851 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2852 }
2853 else
2854 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002855
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002856 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002857}
2858
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002859/*[clinic input]
2860_tkinter.tkapp.createtimerhandler
2861
2862 milliseconds: int
2863 func: object
2864 /
2865
2866[clinic start generated code]*/
2867
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002868static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002869_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2870 PyObject *func)
2871/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002872{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002873 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002874
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002875 if (!PyCallable_Check(func)) {
2876 PyErr_SetString(PyExc_TypeError, "bad argument list");
2877 return NULL;
2878 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002879
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002880 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002881
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002882 v = Tktt_New(func);
2883 if (v) {
2884 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2885 (ClientData)v);
2886 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002888 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002889}
2890
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002891
Guido van Rossum18468821994-06-20 07:49:28 +00002892/** Event Loop **/
2893
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002894/*[clinic input]
2895_tkinter.tkapp.mainloop
2896
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002897 threshold: int = 0
2898 /
2899
2900[clinic start generated code]*/
2901
Guido van Rossum18468821994-06-20 07:49:28 +00002902static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002903_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002904/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002905{
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002906#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002907 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002908#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002909
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002910 CHECK_TCL_APPARTMENT;
2911 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002912
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002913 quitMainLoop = 0;
2914 while (Tk_GetNumMainWindows() > threshold &&
2915 !quitMainLoop &&
2916 !errorInCmd)
2917 {
2918 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002919
2920#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002921 if (self->threaded) {
2922 /* Allow other Python threads to run. */
2923 ENTER_TCL
2924 result = Tcl_DoOneEvent(0);
2925 LEAVE_TCL
2926 }
2927 else {
2928 Py_BEGIN_ALLOW_THREADS
2929 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2930 tcl_tstate = tstate;
2931 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2932 tcl_tstate = NULL;
2933 if(tcl_lock)PyThread_release_lock(tcl_lock);
2934 if (result == 0)
2935 Sleep(Tkinter_busywaitinterval);
2936 Py_END_ALLOW_THREADS
2937 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002938#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002939 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002940#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002941
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002942 if (PyErr_CheckSignals() != 0) {
2943 self->dispatching = 0;
2944 return NULL;
2945 }
2946 if (result < 0)
2947 break;
2948 }
2949 self->dispatching = 0;
2950 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002951
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002952 if (errorInCmd) {
2953 errorInCmd = 0;
2954 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2955 excInCmd = valInCmd = trbInCmd = NULL;
2956 return NULL;
2957 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002958 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002959}
2960
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002961/*[clinic input]
2962_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002963
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002964 flags: int = 0
2965 /
2966
2967[clinic start generated code]*/
2968
2969static PyObject *
2970_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2971/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2972{
2973 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002974
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002975 ENTER_TCL
2976 rv = Tcl_DoOneEvent(flags);
2977 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002978 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002979}
2980
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002981/*[clinic input]
2982_tkinter.tkapp.quit
2983[clinic start generated code]*/
2984
Guido van Rossum062cfb01995-01-10 17:42:51 +00002985static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002986_tkinter_tkapp_quit_impl(TkappObject *self)
2987/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002988{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002989 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002990 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002991}
2992
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002993/*[clinic input]
2994_tkinter.tkapp.interpaddr
2995[clinic start generated code]*/
2996
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002997static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002998_tkinter_tkapp_interpaddr_impl(TkappObject *self)
2999/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003000{
Victor Stinnere1040e22013-09-05 00:22:24 +02003001 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003002}
3003
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003004/*[clinic input]
3005_tkinter.tkapp.loadtk
3006[clinic start generated code]*/
3007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003008static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003009_tkinter_tkapp_loadtk_impl(TkappObject *self)
3010/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00003011{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003012 Tcl_Interp *interp = Tkapp_Interp(self);
3013 const char * _tk_exists = NULL;
3014 int err;
David Aschere2b4b322004-02-18 05:59:53 +00003015
Guilherme Polob681df42009-02-09 22:33:59 +00003016#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003017 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
3018 * first call failed.
3019 * To avoid the deadlock, we just refuse the second call through
3020 * a static variable.
3021 */
3022 if (tk_load_failed) {
3023 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
3024 return NULL;
3025 }
Guilherme Polob681df42009-02-09 22:33:59 +00003026#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003027
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003028 /* We want to guard against calling Tk_Init() multiple times */
3029 CHECK_TCL_APPARTMENT;
3030 ENTER_TCL
3031 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
3032 ENTER_OVERLAP
3033 if (err == TCL_ERROR) {
3034 /* This sets an exception, but we cannot return right
3035 away because we need to exit the overlap first. */
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003036 Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003037 } else {
3038 _tk_exists = Tkapp_Result(self);
3039 }
3040 LEAVE_OVERLAP_TCL
3041 if (err == TCL_ERROR) {
3042 return NULL;
3043 }
3044 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
3045 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003046 PyErr_SetString(Tkinter_TclError,
3047 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00003048#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003049 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00003050#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003051 return NULL;
3052 }
3053 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003054 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00003055}
Barry Warsawfa701a81997-01-16 00:15:11 +00003056
Martin v. Löwisffad6332002-11-26 09:28:05 +00003057static PyObject *
3058Tkapp_WantObjects(PyObject *self, PyObject *args)
3059{
3060
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003061 int wantobjects = -1;
3062 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3063 return NULL;
3064 if (wantobjects == -1)
3065 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3066 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003067
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003068 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003069}
3070
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003071/*[clinic input]
3072_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003073
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003074[clinic start generated code]*/
3075
3076static PyObject *
3077_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03003078/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003079{
3080 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003081
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003082 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003083}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003084
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003085
Guido van Rossum18468821994-06-20 07:49:28 +00003086/**** Tkapp Type Methods ****/
3087
3088static void
Fred Drake509d79a2000-07-08 04:04:38 +00003089Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003090{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003091 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003092 /*CHECK_TCL_APPARTMENT;*/
3093 ENTER_TCL
3094 Tcl_DeleteInterp(Tkapp_Interp(self));
3095 LEAVE_TCL
3096 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003097 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003098 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003099}
3100
Barry Warsawfa701a81997-01-16 00:15:11 +00003101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003102
Guido van Rossum18468821994-06-20 07:49:28 +00003103/**** Tkinter Module ****/
3104
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003105typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003106 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003107 Py_ssize_t size; /* current size */
3108 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003109} FlattenContext;
3110
3111static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003112_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003113{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003114 /* expand tuple to hold (at least) size new items.
3115 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003116
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003117 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003118
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003119 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003120 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003121
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003122 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003123
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003124 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003125}
3126
3127static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003128_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003129{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003130 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003131
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003132 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003134 if (depth > 1000) {
3135 PyErr_SetString(PyExc_ValueError,
3136 "nesting too deep in _flatten");
3137 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003138 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3139 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003140 /* preallocate (assume no nesting) */
3141 if (context->size + size > context->maxsize &&
3142 !_bump(context, size))
3143 return 0;
3144 /* copy items to output tuple */
3145 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003146 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003147 if (PyList_Check(o) || PyTuple_Check(o)) {
3148 if (!_flatten1(context, o, depth + 1))
3149 return 0;
3150 } else if (o != Py_None) {
3151 if (context->size + 1 > context->maxsize &&
3152 !_bump(context, 1))
3153 return 0;
3154 Py_INCREF(o);
3155 PyTuple_SET_ITEM(context->tuple,
3156 context->size++, o);
3157 }
3158 }
3159 } else {
3160 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3161 return 0;
3162 }
3163 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003164}
3165
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003166/*[clinic input]
3167_tkinter._flatten
3168
3169 item: object
3170 /
3171
3172[clinic start generated code]*/
3173
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003174static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003175_tkinter__flatten(PyModuleDef *module, PyObject *item)
3176/*[clinic end generated code: output=9505049ec74c3480 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003177{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003178 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003179
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003180 context.maxsize = PySequence_Size(item);
3181 if (context.maxsize < 0)
3182 return NULL;
3183 if (context.maxsize == 0)
3184 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003185
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003186 context.tuple = PyTuple_New(context.maxsize);
3187 if (!context.tuple)
3188 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003189
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003190 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003191
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003192 if (!_flatten1(&context, item,0))
3193 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003195 if (_PyTuple_Resize(&context.tuple, context.size))
3196 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003198 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003199}
3200
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003201/*[clinic input]
3202_tkinter.create
3203
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003204 screenName: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003205 baseName: str = NULL
3206 className: str = "Tk"
3207 interactive: int(c_default="0") = False
3208 wantobjects: int(c_default="0") = False
3209 wantTk: int(c_default="1") = True
3210 if false, then Tk_Init() doesn't get called
3211 sync: int(c_default="0") = False
3212 if true, then pass -sync to wish
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003213 use: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003214 if not None, then pass -use to wish
3215 /
3216
3217[clinic start generated code]*/
3218
Guido van Rossum18468821994-06-20 07:49:28 +00003219static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003220_tkinter_create_impl(PyModuleDef *module, const char *screenName,
3221 const char *baseName, const char *className,
3222 int interactive, int wantobjects, int wantTk, int sync,
3223 const char *use)
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003224/*[clinic end generated code: output=b8847800fc3b27eb input=0d522aad1cb0ca0e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003225{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003226 /* XXX baseName is not used anymore;
3227 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003228 CHECK_STRING_LENGTH(screenName);
3229 CHECK_STRING_LENGTH(baseName);
3230 CHECK_STRING_LENGTH(className);
3231 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003232
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003233 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003234 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003235 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003236}
3237
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003238/*[clinic input]
3239_tkinter.setbusywaitinterval
3240
3241 new_val: int
3242 /
3243
3244Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3245
3246It should be set to a divisor of the maximum time between frames in an animation.
3247[clinic start generated code]*/
3248
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003249static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003250_tkinter_setbusywaitinterval_impl(PyModuleDef *module, int new_val)
3251/*[clinic end generated code: output=0b9d7ef7940461ea input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003252{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003253 if (new_val < 0) {
3254 PyErr_SetString(PyExc_ValueError,
3255 "busywaitinterval must be >= 0");
3256 return NULL;
3257 }
3258 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003259 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003260}
3261
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003262/*[clinic input]
3263_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003264
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003265Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3266[clinic start generated code]*/
3267
3268static int
3269_tkinter_getbusywaitinterval_impl(PyModuleDef *module)
3270/*[clinic end generated code: output=9d09eee026e96971 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003271{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003272 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003273}
3274
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003275#include "clinic/_tkinter.c.h"
3276
3277static PyMethodDef Tktt_methods[] =
3278{
3279 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3280 {NULL, NULL}
3281};
3282
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003283static PyType_Slot Tktt_Type_slots[] = {
3284 {Py_tp_dealloc, Tktt_Dealloc},
3285 {Py_tp_repr, Tktt_Repr},
3286 {Py_tp_methods, Tktt_methods},
3287 {0, 0}
3288};
3289
3290static PyType_Spec Tktt_Type_spec = {
3291 "_tkinter.tktimertoken",
3292 sizeof(TkttObject),
3293 0,
3294 Py_TPFLAGS_DEFAULT,
3295 Tktt_Type_slots,
3296};
3297
3298
3299/**** Tkapp Method List ****/
3300
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003301static PyMethodDef Tkapp_methods[] =
3302{
3303 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3304 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3305 {"call", Tkapp_Call, METH_VARARGS},
3306 _TKINTER_TKAPP_EVAL_METHODDEF
3307 _TKINTER_TKAPP_EVALFILE_METHODDEF
3308 _TKINTER_TKAPP_RECORD_METHODDEF
3309 _TKINTER_TKAPP_ADDERRINFO_METHODDEF
3310 {"setvar", Tkapp_SetVar, METH_VARARGS},
3311 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3312 {"getvar", Tkapp_GetVar, METH_VARARGS},
3313 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3314 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3315 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3316 _TKINTER_TKAPP_GETINT_METHODDEF
3317 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3318 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3319 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3320 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3321 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3322 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3323 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3324 _TKINTER_TKAPP_SPLIT_METHODDEF
3325 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3326 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3327 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3328 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3329 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3330 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3331 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3332 _TKINTER_TKAPP_QUIT_METHODDEF
3333 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3334 _TKINTER_TKAPP_LOADTK_METHODDEF
3335 {NULL, NULL}
3336};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003337
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003338static PyType_Slot Tkapp_Type_slots[] = {
3339 {Py_tp_dealloc, Tkapp_Dealloc},
3340 {Py_tp_methods, Tkapp_methods},
3341 {0, 0}
3342};
3343
3344
3345static PyType_Spec Tkapp_Type_spec = {
3346 "_tkinter.tkapp",
3347 sizeof(TkappObject),
3348 0,
3349 Py_TPFLAGS_DEFAULT,
3350 Tkapp_Type_slots,
3351};
3352
Guido van Rossum18468821994-06-20 07:49:28 +00003353static PyMethodDef moduleMethods[] =
3354{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003355 _TKINTER__FLATTEN_METHODDEF
3356 _TKINTER_CREATE_METHODDEF
3357 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3358 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003359 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003360};
3361
Guido van Rossum7bf15641998-05-22 18:28:17 +00003362#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003363
3364static int stdin_ready = 0;
3365
Guido van Rossumad4db171998-06-13 13:56:28 +00003366#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003367static void
Fred Drake509d79a2000-07-08 04:04:38 +00003368MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003369{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003370 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003371}
Guido van Rossumad4db171998-06-13 13:56:28 +00003372#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003373
Martin v. Löwisa9656492003-03-30 08:44:58 +00003374#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003375static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003376#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003377
Guido van Rossum18468821994-06-20 07:49:28 +00003378static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003379EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003380{
Guido van Rossumad4db171998-06-13 13:56:28 +00003381#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003382 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003383#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003384#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003385 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003386#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003387 stdin_ready = 0;
3388 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003389#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003390 tfile = fileno(stdin);
3391 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003392#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003393 while (!errorInCmd && !stdin_ready) {
3394 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003395#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003396 if (_kbhit()) {
3397 stdin_ready = 1;
3398 break;
3399 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003400#endif
3401#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003402 Py_BEGIN_ALLOW_THREADS
3403 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3404 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003405
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003406 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003407
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003408 tcl_tstate = NULL;
3409 if(tcl_lock)PyThread_release_lock(tcl_lock);
3410 if (result == 0)
3411 Sleep(Tkinter_busywaitinterval);
3412 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003413#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003414 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003415#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003416
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003417 if (result < 0)
3418 break;
3419 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003420#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003421 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003422#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003423 if (errorInCmd) {
3424 errorInCmd = 0;
3425 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3426 excInCmd = valInCmd = trbInCmd = NULL;
3427 PyErr_Print();
3428 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003429#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003430 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003431#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003432 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003433}
Guido van Rossum18468821994-06-20 07:49:28 +00003434
Guido van Rossum00d93061998-05-28 23:06:38 +00003435#endif
3436
Guido van Rossum7bf15641998-05-22 18:28:17 +00003437static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003438EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003439{
Guido van Rossum00d93061998-05-28 23:06:38 +00003440#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003441 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003442#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003443 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003444#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003445 PyOS_InputHook = EventHook;
3446 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003447#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003448}
3449
3450static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003451DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003452{
Guido van Rossum00d93061998-05-28 23:06:38 +00003453#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003454 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3455 PyOS_InputHook = NULL;
3456 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003457#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003458}
3459
Barry Warsawfa701a81997-01-16 00:15:11 +00003460
Martin v. Löwis1a214512008-06-11 05:26:20 +00003461static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003462 PyModuleDef_HEAD_INIT,
3463 "_tkinter",
3464 NULL,
3465 -1,
3466 moduleMethods,
3467 NULL,
3468 NULL,
3469 NULL,
3470 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003471};
3472
Mark Hammond62b1ab12002-07-23 06:31:15 +00003473PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003474PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003475{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003476 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003477
Guido van Rossum00d93061998-05-28 23:06:38 +00003478#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003479 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003480 if (tcl_lock == NULL)
3481 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003482#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003484 m = PyModule_Create(&_tkintermodule);
3485 if (m == NULL)
3486 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003487
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003488 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3489 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003490 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003491 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003492 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003493 Py_INCREF(o);
3494 if (PyModule_AddObject(m, "TclError", o)) {
3495 Py_DECREF(o);
3496 Py_DECREF(m);
3497 return NULL;
3498 }
3499 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003500
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003501 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3502 Py_DECREF(m);
3503 return NULL;
3504 }
3505 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3506 Py_DECREF(m);
3507 return NULL;
3508 }
3509 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3510 Py_DECREF(m);
3511 return NULL;
3512 }
3513 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3514 Py_DECREF(m);
3515 return NULL;
3516 }
3517 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3518 Py_DECREF(m);
3519 return NULL;
3520 }
3521 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3522 Py_DECREF(m);
3523 return NULL;
3524 }
3525 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3526 Py_DECREF(m);
3527 return NULL;
3528 }
3529 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3530 Py_DECREF(m);
3531 return NULL;
3532 }
3533 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3534 Py_DECREF(m);
3535 return NULL;
3536 }
3537 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3538 Py_DECREF(m);
3539 return NULL;
3540 }
3541 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3542 Py_DECREF(m);
3543 return NULL;
3544 }
3545
3546 o = PyType_FromSpec(&Tkapp_Type_spec);
3547 if (o == NULL) {
3548 Py_DECREF(m);
3549 return NULL;
3550 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003551 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003552 if (PyModule_AddObject(m, "TkappType", o)) {
3553 Py_DECREF(o);
3554 Py_DECREF(m);
3555 return NULL;
3556 }
3557 Tkapp_Type = o;
3558
3559 o = PyType_FromSpec(&Tktt_Type_spec);
3560 if (o == NULL) {
3561 Py_DECREF(m);
3562 return NULL;
3563 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003564 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003565 if (PyModule_AddObject(m, "TkttType", o)) {
3566 Py_DECREF(o);
3567 Py_DECREF(m);
3568 return NULL;
3569 }
3570 Tktt_Type = o;
3571
3572 o = PyType_FromSpec(&PyTclObject_Type_spec);
3573 if (o == NULL) {
3574 Py_DECREF(m);
3575 return NULL;
3576 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003577 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003578 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3579 Py_DECREF(o);
3580 Py_DECREF(m);
3581 return NULL;
3582 }
3583 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003584
3585#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003586 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3587 * start waking up. Note that Tcl_FindExecutable will do this, this
3588 * code must be above it! The original warning from
3589 * tkMacOSXAppInit.c is copied below.
3590 *
3591 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3592 * Tcl interpreter for now. It probably should work to do this
3593 * in the other order, but for now it doesn't seem to.
3594 *
3595 */
3596 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003597#endif
3598
3599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003600 /* This helps the dynamic loader; in Unicode aware Tcl versions
3601 it also helps Tcl find its encodings. */
3602 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3603 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003604 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003605 if (cexe) {
3606#ifdef MS_WINDOWS
3607 int set_var = 0;
3608 PyObject *str_path;
3609 wchar_t *wcs_path;
3610 DWORD ret;
3611
3612 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3613
3614 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3615 str_path = _get_tcl_lib_path();
3616 if (str_path == NULL && PyErr_Occurred()) {
3617 return NULL;
3618 }
3619 if (str_path != NULL) {
3620 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3621 if (wcs_path == NULL) {
3622 return NULL;
3623 }
3624 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3625 set_var = 1;
3626 }
3627 }
3628
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003629 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003630
3631 if (set_var) {
3632 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3633 PyMem_Free(wcs_path);
3634 }
3635#else
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003636 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003637#endif /* MS_WINDOWS */
3638 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003639 Py_XDECREF(cexe);
3640 Py_DECREF(uexe);
3641 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003643 if (PyErr_Occurred()) {
3644 Py_DECREF(m);
3645 return NULL;
3646 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003647
Guido van Rossum43ff8681998-07-14 18:02:13 +00003648#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003649 /* This was not a good idea; through <Destroy> bindings,
3650 Tcl_Finalize() may invoke Python code but at that point the
3651 interpreter and thread state have already been destroyed! */
3652 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003653#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003654 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003655}