blob: 7ed2b0254bd7fd9be12eeecda17f282eaa580bde [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 Storchaka85b0f5b2016-11-20 10:16:47 +0200539 const char *list = PyUnicode_AsUTF8(arg);
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300540
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
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700979#if SIZE_MAX > INT_MAX
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300980#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;
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +0200996 const char *hexchars;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300997 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) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001185 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1186 return PyLong_FromLongLong(wideValue);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001187 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1188 sizeof(wideValue),
1189 PY_LITTLE_ENDIAN,
1190 /* signed */ 1);
1191 }
1192 return NULL;
1193}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001194
1195#ifdef HAVE_LIBTOMMAMTH
1196static PyObject*
1197fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1198{
1199 mp_int bigValue;
1200 unsigned long numBytes;
1201 unsigned char *bytes;
1202 PyObject *res;
1203
1204 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1205 return Tkinter_Error(tkapp);
1206 numBytes = mp_unsigned_bin_size(&bigValue);
1207 bytes = PyMem_Malloc(numBytes);
1208 if (bytes == NULL) {
1209 mp_clear(&bigValue);
1210 return PyErr_NoMemory();
1211 }
1212 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1213 &numBytes) != MP_OKAY) {
1214 mp_clear(&bigValue);
1215 PyMem_Free(bytes);
1216 return PyErr_NoMemory();
1217 }
1218 res = _PyLong_FromByteArray(bytes, numBytes,
1219 /* big-endian */ 0,
1220 /* unsigned */ 0);
1221 PyMem_Free(bytes);
1222 if (res != NULL && bigValue.sign == MP_NEG) {
1223 PyObject *res2 = PyNumber_Negative(res);
1224 Py_DECREF(res);
1225 res = res2;
1226 }
1227 mp_clear(&bigValue);
1228 return res;
1229}
1230#endif
1231
Martin v. Löwisffad6332002-11-26 09:28:05 +00001232static PyObject*
1233FromObj(PyObject* tkapp, Tcl_Obj *value)
1234{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001235 PyObject *result = NULL;
1236 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001237 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001239 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001240 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001241 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001242
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001243 if (value->typePtr == app->BooleanType ||
1244 value->typePtr == app->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001245 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001246 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001247
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001248 if (value->typePtr == app->ByteArrayType) {
1249 int size;
1250 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1251 return PyBytes_FromStringAndSize(data, size);
1252 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001253
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001254 if (value->typePtr == app->DoubleType) {
1255 return PyFloat_FromDouble(value->internalRep.doubleValue);
1256 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001257
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001258 if (value->typePtr == app->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001259 long longValue;
1260 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1261 return PyLong_FromLong(longValue);
1262 /* If there is an error in the long conversion,
1263 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001264 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001265
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001266 if (value->typePtr == app->IntType ||
1267 value->typePtr == app->WideIntType) {
1268 result = fromWideIntObj(tkapp, value);
1269 if (result != NULL || PyErr_Occurred())
1270 return result;
1271 Tcl_ResetResult(interp);
1272 /* If there is an error in the wideInt conversion,
1273 fall through to bignum handling. */
1274 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001275
1276#ifdef HAVE_LIBTOMMAMTH
1277 if (value->typePtr == app->IntType ||
1278 value->typePtr == app->WideIntType ||
1279 value->typePtr == app->BignumType) {
1280 return fromBignumObj(tkapp, value);
1281 }
1282#endif
1283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 if (value->typePtr == app->ListType) {
1285 int size;
1286 int i, status;
1287 PyObject *elem;
1288 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001289
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001290 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001291 if (status == TCL_ERROR)
1292 return Tkinter_Error(tkapp);
1293 result = PyTuple_New(size);
1294 if (!result)
1295 return NULL;
1296 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001297 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001298 if (status == TCL_ERROR) {
1299 Py_DECREF(result);
1300 return Tkinter_Error(tkapp);
1301 }
1302 elem = FromObj(tkapp, tcl_elem);
1303 if (!elem) {
1304 Py_DECREF(result);
1305 return NULL;
1306 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001307 PyTuple_SET_ITEM(result, i, elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001308 }
1309 return result;
1310 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001312 if (value->typePtr == app->ProcBodyType) {
1313 /* fall through: return tcl object. */
1314 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001316 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001317 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001318 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001319 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001320 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001321
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001322#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001323 if (app->BooleanType == NULL &&
1324 strcmp(value->typePtr->name, "booleanString") == 0) {
1325 /* booleanString type is not registered in Tcl */
1326 app->BooleanType = value->typePtr;
1327 return fromBoolean(tkapp, value);
1328 }
1329#endif
1330
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001331#ifdef HAVE_LIBTOMMAMTH
1332 if (app->BignumType == NULL &&
1333 strcmp(value->typePtr->name, "bignum") == 0) {
1334 /* bignum type is not registered in Tcl */
1335 app->BignumType = value->typePtr;
1336 return fromBignumObj(tkapp, value);
1337 }
1338#endif
1339
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001340 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001341}
1342
Benjamin Peterson5879d412009-03-30 14:51:56 +00001343#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001344/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001345TCL_DECLARE_MUTEX(call_mutex)
1346
1347typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001348 Tcl_Event ev; /* Must be first */
1349 TkappObject *self;
1350 PyObject *args;
1351 int flags;
1352 PyObject **res;
1353 PyObject **exc_type, **exc_value, **exc_tb;
1354 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001355} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001356#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001357
1358void
1359Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001360{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001361 int i;
1362 for (i = 0; i < objc; i++)
1363 Tcl_DecrRefCount(objv[i]);
1364 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001365 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001366}
Guido van Rossum18468821994-06-20 07:49:28 +00001367
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001368/* Convert Python objects to Tcl objects. This must happen in the
1369 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001370
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001371static Tcl_Obj**
1372Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1373{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001374 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001375 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001376 if (args == NULL)
1377 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001378
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001379 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001380 objv[0] = AsObj(args);
Serhiy Storchaka0b3ec192017-03-23 17:53:47 +02001381 if (objv[0] == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001382 goto finally;
1383 objc = 1;
1384 Tcl_IncrRefCount(objv[0]);
1385 }
1386 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001387 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001389 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001390 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001391 PyErr_SetString(PyExc_OverflowError,
1392 PyTuple_Check(args) ? "tuple is too long" :
1393 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001394 return NULL;
1395 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001396 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001397 if (objv == NULL) {
1398 PyErr_NoMemory();
1399 objc = 0;
1400 goto finally;
1401 }
1402 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001403
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001404 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001405 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001406 if (v == Py_None) {
1407 objc = i;
1408 break;
1409 }
1410 objv[i] = AsObj(v);
1411 if (!objv[i]) {
1412 /* Reset objc, so it attempts to clear
1413 objects only up to i. */
1414 objc = i;
1415 goto finally;
1416 }
1417 Tcl_IncrRefCount(objv[i]);
1418 }
1419 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001420 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001421 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001422finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001423 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001424 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001425}
Guido van Rossum212643f1998-04-29 16:22:14 +00001426
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001427/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001428
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001429static PyObject*
1430Tkapp_CallResult(TkappObject *self)
1431{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001432 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001433 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001434 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001435 /* Not sure whether the IncrRef is necessary, but something
1436 may overwrite the interpreter result while we are
1437 converting it. */
1438 Tcl_IncrRefCount(value);
1439 res = FromObj((PyObject*)self, value);
1440 Tcl_DecrRefCount(value);
1441 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001442 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001443 }
1444 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001445}
Guido van Rossum632de272000-03-29 00:19:50 +00001446
Benjamin Peterson5879d412009-03-30 14:51:56 +00001447#ifdef WITH_THREAD
1448
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001449/* Tkapp_CallProc is the event procedure that is executed in the context of
1450 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1451 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001452
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001453static int
1454Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1455{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001456 Tcl_Obj *objStore[ARGSZ];
1457 Tcl_Obj **objv;
1458 int objc;
1459 int i;
1460 ENTER_PYTHON
1461 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1462 if (!objv) {
1463 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1464 *(e->res) = NULL;
1465 }
1466 LEAVE_PYTHON
1467 if (!objv)
1468 goto done;
1469 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1470 ENTER_PYTHON
1471 if (i == TCL_ERROR) {
1472 *(e->res) = NULL;
1473 *(e->exc_type) = NULL;
1474 *(e->exc_tb) = NULL;
1475 *(e->exc_value) = PyObject_CallFunction(
1476 Tkinter_TclError, "s",
1477 Tcl_GetStringResult(e->self->interp));
1478 }
1479 else {
1480 *(e->res) = Tkapp_CallResult(e->self);
1481 }
1482 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001485done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001486 /* Wake up calling thread. */
1487 Tcl_MutexLock(&call_mutex);
1488 Tcl_ConditionNotify(e->done);
1489 Tcl_MutexUnlock(&call_mutex);
1490 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001491}
1492
Benjamin Peterson5879d412009-03-30 14:51:56 +00001493#endif
1494
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001495/* This is the main entry point for calling a Tcl command.
1496 It supports three cases, with regard to threading:
1497 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1498 the context of the calling thread.
1499 2. Tcl is threaded, caller of the command is in the interpreter thread:
1500 Execute the command in the calling thread. Since the Tcl lock will
1501 not be used, we can merge that with case 1.
1502 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1503 the interpreter thread. Allocation of Tcl objects needs to occur in the
1504 interpreter thread, so we ship the PyObject* args to the target thread,
1505 and perform processing there. */
1506
1507static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001508Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001509{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510 Tcl_Obj *objStore[ARGSZ];
1511 Tcl_Obj **objv = NULL;
1512 int objc, i;
1513 PyObject *res = NULL;
1514 TkappObject *self = (TkappObject*)selfptr;
1515 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001517 /* If args is a single tuple, replace with contents of tuple */
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001518 if (PyTuple_GET_SIZE(args) == 1) {
1519 PyObject *item = PyTuple_GET_ITEM(args, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001520 if (PyTuple_Check(item))
1521 args = item;
1522 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001523#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001524 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1525 /* We cannot call the command directly. Instead, we must
1526 marshal the parameters to the interpreter thread. */
1527 Tkapp_CallEvent *ev;
1528 Tcl_Condition cond = NULL;
1529 PyObject *exc_type, *exc_value, *exc_tb;
1530 if (!WaitForMainloop(self))
1531 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001532 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1533 if (ev == NULL) {
1534 PyErr_NoMemory();
1535 return NULL;
1536 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001537 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1538 ev->self = self;
1539 ev->args = args;
1540 ev->res = &res;
1541 ev->exc_type = &exc_type;
1542 ev->exc_value = &exc_value;
1543 ev->exc_tb = &exc_tb;
1544 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001546 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001548 if (res == NULL) {
1549 if (exc_type)
1550 PyErr_Restore(exc_type, exc_value, exc_tb);
1551 else
1552 PyErr_SetObject(Tkinter_TclError, exc_value);
1553 }
1554 Tcl_ConditionFinalize(&cond);
1555 }
1556 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001557#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001558 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001559
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001560 objv = Tkapp_CallArgs(args, objStore, &objc);
1561 if (!objv)
1562 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001564 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001565
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001567
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001569
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001570 if (i == TCL_ERROR)
1571 Tkinter_Error(selfptr);
1572 else
1573 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001574
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001575 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001576
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001577 Tkapp_CallDeallocArgs(objv, objStore, objc);
1578 }
1579 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001580}
1581
1582
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001583/*[clinic input]
1584_tkinter.tkapp.eval
1585
1586 script: str
1587 /
1588
1589[clinic start generated code]*/
1590
Barry Warsawfa701a81997-01-16 00:15:11 +00001591static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001592_tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1593/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001594{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001595 PyObject *res = NULL;
1596 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001597
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001598 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001599 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001601 ENTER_TCL
1602 err = Tcl_Eval(Tkapp_Interp(self), script);
1603 ENTER_OVERLAP
1604 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001605 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001606 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001607 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001608 LEAVE_OVERLAP_TCL
1609 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001610}
1611
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001612/*[clinic input]
1613_tkinter.tkapp.evalfile
1614
1615 fileName: str
1616 /
1617
1618[clinic start generated code]*/
1619
Guido van Rossum18468821994-06-20 07:49:28 +00001620static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001621_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1622/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001623{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001624 PyObject *res = NULL;
1625 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001626
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001627 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001628 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001629
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001630 ENTER_TCL
1631 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1632 ENTER_OVERLAP
1633 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001634 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001635 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001636 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001637 LEAVE_OVERLAP_TCL
1638 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001639}
1640
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001641/*[clinic input]
1642_tkinter.tkapp.record
1643
1644 script: str
1645 /
1646
1647[clinic start generated code]*/
1648
Guido van Rossum18468821994-06-20 07:49:28 +00001649static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001650_tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1651/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
Guido van Rossum18468821994-06-20 07:49:28 +00001652{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001653 PyObject *res = NULL;
1654 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001655
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001656 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001657 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001659 ENTER_TCL
1660 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1661 ENTER_OVERLAP
1662 if (err == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001663 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001664 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001665 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001666 LEAVE_OVERLAP_TCL
1667 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001668}
1669
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001670/*[clinic input]
1671_tkinter.tkapp.adderrinfo
Guido van Rossum18468821994-06-20 07:49:28 +00001672
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001673 msg: str
1674 /
1675
1676[clinic start generated code]*/
1677
1678static PyObject *
1679_tkinter_tkapp_adderrinfo_impl(TkappObject *self, const char *msg)
1680/*[clinic end generated code: output=0e222ee2050eb357 input=4971399317d4c136]*/
1681{
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001682 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001683 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001684
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001685 ENTER_TCL
1686 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1687 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001688
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001689 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001690}
1691
Barry Warsawfa701a81997-01-16 00:15:11 +00001692
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001693
Guido van Rossum18468821994-06-20 07:49:28 +00001694/** Tcl Variable **/
1695
Benjamin Peterson5879d412009-03-30 14:51:56 +00001696typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1697
1698#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001699TCL_DECLARE_MUTEX(var_mutex)
1700
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001701typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001702 Tcl_Event ev; /* must be first */
1703 PyObject *self;
1704 PyObject *args;
1705 int flags;
1706 EventFunc func;
1707 PyObject **res;
1708 PyObject **exc_type;
1709 PyObject **exc_val;
1710 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001711} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001712#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001713
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001714/*[python]
1715
1716class varname_converter(CConverter):
1717 type = 'const char *'
1718 converter = 'varname_converter'
1719
1720[python]*/
1721/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1722
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001723static int
1724varname_converter(PyObject *in, void *_out)
1725{
Serhiy Storchaka85b0f5b2016-11-20 10:16:47 +02001726 const char *s;
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001727 const char **out = (const char**)_out;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001728 if (PyBytes_Check(in)) {
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001729 if (PyBytes_GET_SIZE(in) > INT_MAX) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001730 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1731 return 0;
1732 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03001733 s = PyBytes_AS_STRING(in);
1734 if (strlen(s) != (size_t)PyBytes_GET_SIZE(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001735 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001736 return 0;
1737 }
1738 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001739 return 1;
1740 }
1741 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001742 Py_ssize_t size;
1743 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001744 if (s == NULL) {
1745 return 0;
1746 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001747 if (size > INT_MAX) {
1748 PyErr_SetString(PyExc_OverflowError, "string is too long");
1749 return 0;
1750 }
Victor Stinner706768c2014-08-16 01:03:39 +02001751 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001752 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001753 return 0;
1754 }
1755 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001756 return 1;
1757 }
1758 if (PyTclObject_Check(in)) {
1759 *out = PyTclObject_TclString(in);
1760 return 1;
1761 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001762 PyErr_Format(PyExc_TypeError,
1763 "must be str, bytes or Tcl_Obj, not %.50s",
1764 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001765 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001766}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001767
Benjamin Peterson5879d412009-03-30 14:51:56 +00001768#ifdef WITH_THREAD
1769
Martin v. Löwis59683e82008-06-13 07:50:45 +00001770static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001771var_perform(VarEvent *ev)
1772{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001773 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1774 if (!*(ev->res)) {
1775 PyObject *exc, *val, *tb;
1776 PyErr_Fetch(&exc, &val, &tb);
1777 PyErr_NormalizeException(&exc, &val, &tb);
1778 *(ev->exc_type) = exc;
1779 *(ev->exc_val) = val;
Serhiy Storchaka3ec5f422016-10-28 12:14:34 +03001780 Py_XDECREF(tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001781 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001782
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001783}
1784
1785static int
1786var_proc(VarEvent* ev, int flags)
1787{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001788 ENTER_PYTHON
1789 var_perform(ev);
1790 Tcl_MutexLock(&var_mutex);
1791 Tcl_ConditionNotify(ev->cond);
1792 Tcl_MutexUnlock(&var_mutex);
1793 LEAVE_PYTHON
1794 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001795}
1796
Benjamin Peterson5879d412009-03-30 14:51:56 +00001797#endif
1798
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001799static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001800var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001801{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001802#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001803 TkappObject *self = (TkappObject*)selfptr;
1804 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001805 VarEvent *ev;
1806 PyObject *res, *exc_type, *exc_val;
1807 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001808
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001809 /* The current thread is not the interpreter thread. Marshal
1810 the call to the interpreter thread, then wait for
1811 completion. */
1812 if (!WaitForMainloop(self))
1813 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001814
Serhiy Storchaka07940882014-09-11 10:38:54 +03001815 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1816 if (ev == NULL) {
1817 PyErr_NoMemory();
1818 return NULL;
1819 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001820 ev->self = selfptr;
1821 ev->args = args;
1822 ev->flags = flags;
1823 ev->func = func;
1824 ev->res = &res;
1825 ev->exc_type = &exc_type;
1826 ev->exc_val = &exc_val;
1827 ev->cond = &cond;
1828 ev->ev.proc = (Tcl_EventProc*)var_proc;
1829 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1830 Tcl_ConditionFinalize(&cond);
1831 if (!res) {
1832 PyErr_SetObject(exc_type, exc_val);
1833 Py_DECREF(exc_type);
1834 Py_DECREF(exc_val);
1835 return NULL;
1836 }
1837 return res;
1838 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001839#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001840 /* Tcl is not threaded, or this is the interpreter thread. */
1841 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001842}
1843
Guido van Rossum18468821994-06-20 07:49:28 +00001844static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001845SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001846{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001847 const char *name1, *name2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001848 PyObject *newValue;
1849 PyObject *res = NULL;
1850 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001851
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001852 switch (PyTuple_GET_SIZE(args)) {
1853 case 2:
1854 if (!PyArg_ParseTuple(args, "O&O:setvar",
1855 varname_converter, &name1, &newValue))
1856 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001857 /* XXX Acquire tcl lock??? */
1858 newval = AsObj(newValue);
1859 if (newval == NULL)
1860 return NULL;
1861 ENTER_TCL
1862 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1863 newval, flags);
1864 ENTER_OVERLAP
1865 if (!ok)
1866 Tkinter_Error(self);
1867 else {
1868 res = Py_None;
1869 Py_INCREF(res);
1870 }
1871 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001872 break;
1873 case 3:
1874 if (!PyArg_ParseTuple(args, "ssO:setvar",
1875 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001876 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001877 CHECK_STRING_LENGTH(name1);
1878 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001879 /* XXX must hold tcl lock already??? */
1880 newval = AsObj(newValue);
1881 ENTER_TCL
1882 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1883 ENTER_OVERLAP
1884 if (!ok)
1885 Tkinter_Error(self);
1886 else {
1887 res = Py_None;
1888 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001889 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001890 LEAVE_OVERLAP_TCL
1891 break;
1892 default:
1893 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1894 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001895 }
1896 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001897}
1898
1899static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001900Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001901{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001902 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001903}
1904
1905static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001906Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001907{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001908 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001909}
1910
Barry Warsawfa701a81997-01-16 00:15:11 +00001911
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001912
Guido van Rossum18468821994-06-20 07:49:28 +00001913static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001914GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001915{
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001916 const char *name1, *name2=NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001917 PyObject *res = NULL;
1918 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001919
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001920 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1921 varname_converter, &name1, &name2))
1922 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001923
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001924 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001925 ENTER_TCL
1926 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1927 ENTER_OVERLAP
1928 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001929 PyErr_SetString(Tkinter_TclError,
1930 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001931 } else {
1932 if (((TkappObject*)self)->wantobjects) {
1933 res = FromObj(self, tres);
1934 }
1935 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001936 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001937 }
1938 }
1939 LEAVE_OVERLAP_TCL
1940 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001941}
1942
1943static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001944Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001945{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001946 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001947}
1948
1949static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001950Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001951{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001952 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001953}
1954
Barry Warsawfa701a81997-01-16 00:15:11 +00001955
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001956
Guido van Rossum18468821994-06-20 07:49:28 +00001957static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001958UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001959{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001960 char *name1, *name2=NULL;
1961 int code;
1962 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001963
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001964 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1965 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001966
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001967 CHECK_STRING_LENGTH(name1);
1968 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001969 ENTER_TCL
1970 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1971 ENTER_OVERLAP
1972 if (code == TCL_ERROR)
1973 res = Tkinter_Error(self);
1974 else {
1975 Py_INCREF(Py_None);
1976 res = Py_None;
1977 }
1978 LEAVE_OVERLAP_TCL
1979 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001980}
1981
1982static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001983Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001984{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001985 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001986}
1987
1988static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001989Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001990{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001991 return var_invoke(UnsetVar, self, args,
1992 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001993}
1994
Barry Warsawfa701a81997-01-16 00:15:11 +00001995
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001996
Guido van Rossum18468821994-06-20 07:49:28 +00001997/** Tcl to Python **/
1998
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03001999/*[clinic input]
2000_tkinter.tkapp.getint
2001
2002 arg: object
2003 /
2004
2005[clinic start generated code]*/
2006
Guido van Rossum18468821994-06-20 07:49:28 +00002007static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002008_tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
2009/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002010{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002011 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002012 Tcl_Obj *value;
2013 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00002014
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002015 if (PyLong_Check(arg)) {
2016 Py_INCREF(arg);
2017 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002018 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002019
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002020 if (PyTclObject_Check(arg)) {
2021 value = ((PyTclObject*)arg)->value;
2022 Tcl_IncrRefCount(value);
2023 }
2024 else {
2025 if (!PyArg_Parse(arg, "s:getint", &s))
2026 return NULL;
2027 CHECK_STRING_LENGTH(s);
2028 value = Tcl_NewStringObj(s, -1);
2029 if (value == NULL)
2030 return Tkinter_Error((PyObject *)self);
2031 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002032 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
2033 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
2034
2035 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
2036 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
2037 */
2038#ifdef HAVE_LIBTOMMAMTH
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002039 result = fromBignumObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002040#else
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002041 result = fromWideIntObj((PyObject *)self, value);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03002042#endif
2043 Tcl_DecrRefCount(value);
2044 if (result != NULL || PyErr_Occurred())
2045 return result;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002046 return Tkinter_Error((PyObject *)self);
Guido van Rossum18468821994-06-20 07:49:28 +00002047}
2048
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002049/*[clinic input]
2050_tkinter.tkapp.getdouble
2051
2052 arg: object
2053 /
2054
2055[clinic start generated code]*/
2056
Guido van Rossum18468821994-06-20 07:49:28 +00002057static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002058_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
2059/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002060{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002061 char *s;
2062 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00002063
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002064 if (PyFloat_Check(arg)) {
2065 Py_INCREF(arg);
2066 return arg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002067 }
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002068
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002069 if (PyNumber_Check(arg)) {
2070 return PyNumber_Float(arg);
2071 }
2072
2073 if (PyTclObject_Check(arg)) {
2074 if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
2075 ((PyTclObject*)arg)->value,
2076 &v) == TCL_ERROR)
2077 return Tkinter_Error((PyObject *)self);
2078 return PyFloat_FromDouble(v);
2079 }
2080
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002081 if (!PyArg_Parse(arg, "s:getdouble", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002082 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002083 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002084 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002085 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka645058d2015-05-06 14:00:04 +03002086 return PyFloat_FromDouble(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002087}
2088
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002089/*[clinic input]
2090_tkinter.tkapp.getboolean
2091
2092 arg: object
2093 /
2094
2095[clinic start generated code]*/
2096
Guido van Rossum18468821994-06-20 07:49:28 +00002097static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002098_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
2099/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002100{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002101 char *s;
2102 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002103
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002104 if (PyLong_Check(arg)) { /* int or bool */
2105 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002106 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002107
2108 if (PyTclObject_Check(arg)) {
2109 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2110 ((PyTclObject*)arg)->value,
2111 &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002112 return Tkinter_Error((PyObject *)self);
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002113 return PyBool_FromLong(v);
2114 }
2115
2116 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002117 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002118 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002119 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002120 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002121 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002122}
2123
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002124/*[clinic input]
2125_tkinter.tkapp.exprstring
2126
2127 s: str
2128 /
2129
2130[clinic start generated code]*/
2131
Guido van Rossum18468821994-06-20 07:49:28 +00002132static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002133_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2134/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002135{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002136 PyObject *res = NULL;
2137 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002138
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002139 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002140 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002141
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142 ENTER_TCL
2143 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2144 ENTER_OVERLAP
2145 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002146 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002147 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002148 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002149 LEAVE_OVERLAP_TCL
2150 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002151}
2152
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002153/*[clinic input]
2154_tkinter.tkapp.exprlong
2155
2156 s: str
2157 /
2158
2159[clinic start generated code]*/
2160
Guido van Rossum18468821994-06-20 07:49:28 +00002161static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002162_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2163/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002164{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002165 PyObject *res = NULL;
2166 int retval;
2167 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002168
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002169 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002170 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002171
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002172 ENTER_TCL
2173 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2174 ENTER_OVERLAP
2175 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002176 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002177 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002178 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002179 LEAVE_OVERLAP_TCL
2180 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002181}
2182
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002183/*[clinic input]
2184_tkinter.tkapp.exprdouble
2185
2186 s: str
2187 /
2188
2189[clinic start generated code]*/
2190
Guido van Rossum18468821994-06-20 07:49:28 +00002191static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002192_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2193/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002194{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002195 PyObject *res = NULL;
2196 double v;
2197 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002198
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002199 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002200 CHECK_TCL_APPARTMENT;
2201 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2202 ENTER_TCL
2203 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2204 ENTER_OVERLAP
2205 PyFPE_END_PROTECT(retval)
2206 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002207 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002208 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002209 res = PyFloat_FromDouble(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002210 LEAVE_OVERLAP_TCL
2211 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002212}
2213
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002214/*[clinic input]
2215_tkinter.tkapp.exprboolean
2216
2217 s: str
2218 /
2219
2220[clinic start generated code]*/
2221
Guido van Rossum18468821994-06-20 07:49:28 +00002222static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002223_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2224/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002225{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002226 PyObject *res = NULL;
2227 int retval;
2228 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002229
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002230 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002231 CHECK_TCL_APPARTMENT;
2232 ENTER_TCL
2233 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2234 ENTER_OVERLAP
2235 if (retval == TCL_ERROR)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002236 res = Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002237 else
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002238 res = PyLong_FromLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002239 LEAVE_OVERLAP_TCL
2240 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002241}
2242
Barry Warsawfa701a81997-01-16 00:15:11 +00002243
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002244
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002245/*[clinic input]
2246_tkinter.tkapp.splitlist
2247
2248 arg: object
2249 /
2250
2251[clinic start generated code]*/
2252
Guido van Rossum18468821994-06-20 07:49:28 +00002253static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002254_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2255/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002256{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002257 char *list;
2258 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002259 const char **argv;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002260 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002261 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002262
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002263 if (PyTclObject_Check(arg)) {
2264 int objc;
2265 Tcl_Obj **objv;
2266 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2267 ((PyTclObject*)arg)->value,
2268 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002269 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002270 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002271 if (!(v = PyTuple_New(objc)))
2272 return NULL;
2273 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002274 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002275 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002276 Py_DECREF(v);
2277 return NULL;
2278 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002279 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002280 }
2281 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002282 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002283 if (PyTuple_Check(arg)) {
2284 Py_INCREF(arg);
2285 return arg;
2286 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002287 if (PyList_Check(arg)) {
2288 return PySequence_Tuple(arg);
2289 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002290
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002291 if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002292 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002293
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002294 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002295 if (Tcl_SplitList(Tkapp_Interp(self), list,
2296 &argc, &argv) == TCL_ERROR) {
2297 PyMem_Free(list);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002298 return Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299 }
Guido van Rossum18468821994-06-20 07:49:28 +00002300
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002301 if (!(v = PyTuple_New(argc)))
2302 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002303
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002304 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002305 PyObject *s = unicodeFromTclString(argv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002306 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002307 Py_DECREF(v);
2308 v = NULL;
2309 goto finally;
2310 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002311 PyTuple_SET_ITEM(v, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002312 }
Guido van Rossum18468821994-06-20 07:49:28 +00002313
Barry Warsawfa701a81997-01-16 00:15:11 +00002314 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002315 ckfree(FREECAST argv);
2316 PyMem_Free(list);
2317 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002318}
2319
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002320/*[clinic input]
2321_tkinter.tkapp.split
2322
2323 arg: object
2324 /
2325
2326[clinic start generated code]*/
2327
Guido van Rossum18468821994-06-20 07:49:28 +00002328static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002329_tkinter_tkapp_split(TkappObject *self, PyObject *arg)
2330/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002331{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002332 PyObject *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002333 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002334
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002335 if (PyTclObject_Check(arg)) {
2336 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2337 int objc;
2338 Tcl_Obj **objv;
2339 int i;
2340 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2341 &objc, &objv) == TCL_ERROR) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002342 return FromObj((PyObject*)self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002343 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002344 if (objc == 0)
2345 return PyUnicode_FromString("");
2346 if (objc == 1)
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002347 return FromObj((PyObject*)self, objv[0]);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002348 if (!(v = PyTuple_New(objc)))
2349 return NULL;
2350 for (i = 0; i < objc; i++) {
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002351 PyObject *s = FromObj((PyObject*)self, objv[i]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002352 if (!s) {
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002353 Py_DECREF(v);
2354 return NULL;
2355 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002356 PyTuple_SET_ITEM(v, i, s);
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002357 }
2358 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002359 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002360 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002361 return SplitObj(arg);
2362
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002363 if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002364 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002365 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002366 v = Split(list);
2367 PyMem_Free(list);
2368 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002369}
2370
Barry Warsawfa701a81997-01-16 00:15:11 +00002371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002372
Guido van Rossum18468821994-06-20 07:49:28 +00002373/** Tcl Command **/
2374
Guido van Rossum00d93061998-05-28 23:06:38 +00002375/* Client data struct */
2376typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002377 PyObject *self;
2378 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002379} PythonCmd_ClientData;
2380
2381static int
Fred Drake509d79a2000-07-08 04:04:38 +00002382PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002383{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002384 errorInCmd = 1;
2385 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2386 LEAVE_PYTHON
2387 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002388}
2389
Guido van Rossum18468821994-06-20 07:49:28 +00002390/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002391 * function or method.
2392 */
Guido van Rossum18468821994-06-20 07:49:28 +00002393static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002394PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002395{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002396 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002397 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002398 int i, rv;
2399 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002401 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002403 /* TBD: no error checking here since we know, via the
2404 * Tkapp_CreateCommand() that the client data is a two-tuple
2405 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002406 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002407
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002408 /* Create argument list (argv1, ..., argvN) */
2409 if (!(arg = PyTuple_New(argc - 1)))
2410 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002411
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002412 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002413 PyObject *s = unicodeFromTclString(argv[i + 1]);
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002414 if (!s) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002415 Py_DECREF(arg);
2416 return PythonCmd_Error(interp);
2417 }
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03002418 PyTuple_SET_ITEM(arg, i, s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002419 }
INADA Naoki72dccde2017-02-16 09:26:01 +09002420 res = PyObject_Call(func, arg, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002421 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002422
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002423 if (res == NULL)
2424 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002426 obj_res = AsObj(res);
2427 if (obj_res == NULL) {
2428 Py_DECREF(res);
2429 return PythonCmd_Error(interp);
2430 }
2431 else {
2432 Tcl_SetObjResult(interp, obj_res);
2433 rv = TCL_OK;
2434 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002435
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002436 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002438 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002439
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002440 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002441}
2442
2443static void
Fred Drake509d79a2000-07-08 04:04:38 +00002444PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002445{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002446 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002447
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002448 ENTER_PYTHON
2449 Py_XDECREF(data->self);
2450 Py_XDECREF(data->func);
2451 PyMem_DEL(data);
2452 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002453}
2454
Barry Warsawfa701a81997-01-16 00:15:11 +00002455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002456
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002457
Benjamin Peterson5879d412009-03-30 14:51:56 +00002458#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002459TCL_DECLARE_MUTEX(command_mutex)
2460
2461typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002462 Tcl_Event ev;
2463 Tcl_Interp* interp;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002464 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002465 int create;
2466 int *status;
2467 ClientData *data;
2468 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002469} CommandEvent;
2470
2471static int
2472Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002473{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002474 if (ev->create)
2475 *ev->status = Tcl_CreateCommand(
2476 ev->interp, ev->name, PythonCmd,
2477 ev->data, PythonCmdDelete) == NULL;
2478 else
2479 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2480 Tcl_MutexLock(&command_mutex);
2481 Tcl_ConditionNotify(ev->done);
2482 Tcl_MutexUnlock(&command_mutex);
2483 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002484}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002485#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002486
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002487/*[clinic input]
2488_tkinter.tkapp.createcommand
2489
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002490 name: str
2491 func: object
2492 /
2493
2494[clinic start generated code]*/
2495
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002496static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002497_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2498 PyObject *func)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002499/*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002500{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002501 PythonCmd_ClientData *data;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002502 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002503
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002504 CHECK_STRING_LENGTH(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002505 if (!PyCallable_Check(func)) {
2506 PyErr_SetString(PyExc_TypeError, "command not callable");
2507 return NULL;
2508 }
Guido van Rossum18468821994-06-20 07:49:28 +00002509
Martin v. Löwisa9656492003-03-30 08:44:58 +00002510#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002511 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2512 !WaitForMainloop(self))
2513 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002514#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002515
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002516 data = PyMem_NEW(PythonCmd_ClientData, 1);
2517 if (!data)
2518 return PyErr_NoMemory();
2519 Py_INCREF(self);
2520 Py_INCREF(func);
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002521 data->self = (PyObject *) self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002522 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002523#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002524 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2525 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002526 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2527 if (ev == NULL) {
2528 PyErr_NoMemory();
2529 PyMem_DEL(data);
2530 return NULL;
2531 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002532 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2533 ev->interp = self->interp;
2534 ev->create = 1;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002535 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002536 ev->data = (ClientData)data;
2537 ev->status = &err;
2538 ev->done = &cond;
2539 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2540 Tcl_ConditionFinalize(&cond);
2541 }
2542 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002543#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002544 {
2545 ENTER_TCL
2546 err = Tcl_CreateCommand(
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002547 Tkapp_Interp(self), name, PythonCmd,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002548 (ClientData)data, PythonCmdDelete) == NULL;
2549 LEAVE_TCL
2550 }
2551 if (err) {
2552 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2553 PyMem_DEL(data);
2554 return NULL;
2555 }
Guido van Rossum18468821994-06-20 07:49:28 +00002556
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002557 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002558}
2559
Barry Warsawfa701a81997-01-16 00:15:11 +00002560
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002561
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002562/*[clinic input]
2563_tkinter.tkapp.deletecommand
2564
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002565 name: str
2566 /
2567
2568[clinic start generated code]*/
2569
Guido van Rossum18468821994-06-20 07:49:28 +00002570static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002571_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002572/*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002573{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002574 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002575
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002576 CHECK_STRING_LENGTH(name);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002577
2578#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2580 Tcl_Condition cond = NULL;
2581 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002582 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2583 if (ev == NULL) {
2584 PyErr_NoMemory();
2585 return NULL;
2586 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002587 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2588 ev->interp = self->interp;
2589 ev->create = 0;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002590 ev->name = name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002591 ev->status = &err;
2592 ev->done = &cond;
2593 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2594 &command_mutex);
2595 Tcl_ConditionFinalize(&cond);
2596 }
2597 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002598#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002599 {
2600 ENTER_TCL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002601 err = Tcl_DeleteCommand(self->interp, name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002602 LEAVE_TCL
2603 }
2604 if (err == -1) {
2605 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2606 return NULL;
2607 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002608 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002609}
2610
Barry Warsawfa701a81997-01-16 00:15:11 +00002611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002612
Guido van Rossum00d93061998-05-28 23:06:38 +00002613#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002614/** File Handler **/
2615
Guido van Rossum00d93061998-05-28 23:06:38 +00002616typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002617 PyObject *func;
2618 PyObject *file;
2619 int id;
2620 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002621} FileHandler_ClientData;
2622
2623static FileHandler_ClientData *HeadFHCD;
2624
2625static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002626NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002627{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002628 FileHandler_ClientData *p;
2629 p = PyMem_NEW(FileHandler_ClientData, 1);
2630 if (p != NULL) {
2631 Py_XINCREF(func);
2632 Py_XINCREF(file);
2633 p->func = func;
2634 p->file = file;
2635 p->id = id;
2636 p->next = HeadFHCD;
2637 HeadFHCD = p;
2638 }
2639 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002640}
2641
2642static void
Fred Drake509d79a2000-07-08 04:04:38 +00002643DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002644{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002645 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002647 pp = &HeadFHCD;
2648 while ((p = *pp) != NULL) {
2649 if (p->id == id) {
2650 *pp = p->next;
2651 Py_XDECREF(p->func);
2652 Py_XDECREF(p->file);
2653 PyMem_DEL(p);
2654 }
2655 else
2656 pp = &p->next;
2657 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002658}
2659
Guido van Rossuma597dde1995-01-10 20:56:29 +00002660static void
Fred Drake509d79a2000-07-08 04:04:38 +00002661FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002662{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002663 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
INADA Naoki72dccde2017-02-16 09:26:01 +09002664 PyObject *func, *file, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002666 ENTER_PYTHON
2667 func = data->func;
2668 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002669
INADA Naoki72dccde2017-02-16 09:26:01 +09002670 res = PyObject_CallFunction(func, "Oi", file, mask);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002671 if (res == NULL) {
2672 errorInCmd = 1;
2673 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2674 }
2675 Py_XDECREF(res);
2676 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002677}
2678
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002679/*[clinic input]
2680_tkinter.tkapp.createfilehandler
2681
2682 file: object
2683 mask: int
2684 func: object
2685 /
2686
2687[clinic start generated code]*/
2688
Guido van Rossum18468821994-06-20 07:49:28 +00002689static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002690_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2691 int mask, PyObject *func)
2692/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002693{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002694 FileHandler_ClientData *data;
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002695 int tfile;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002696
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002697 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002698
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002699 tfile = PyObject_AsFileDescriptor(file);
2700 if (tfile < 0)
2701 return NULL;
2702 if (!PyCallable_Check(func)) {
2703 PyErr_SetString(PyExc_TypeError, "bad argument list");
2704 return NULL;
2705 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002706
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002707 data = NewFHCD(func, file, tfile);
2708 if (data == NULL)
2709 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002710
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002711 /* Ought to check for null Tcl_File object... */
2712 ENTER_TCL
2713 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2714 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002715 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002716}
2717
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002718/*[clinic input]
2719_tkinter.tkapp.deletefilehandler
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002720
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002721 file: object
2722 /
2723
2724[clinic start generated code]*/
2725
2726static PyObject *
2727_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2728/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2729{
2730 int tfile;
Neal Norwitz12e22172003-03-03 21:16:39 +00002731
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002732 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002733
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002734 tfile = PyObject_AsFileDescriptor(file);
2735 if (tfile < 0)
2736 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002737
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002738 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002739
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002740 /* Ought to check for null Tcl_File object... */
2741 ENTER_TCL
2742 Tcl_DeleteFileHandler(tfile);
2743 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002744 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002745}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002746#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002747
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002748
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002749/**** Tktt Object (timer token) ****/
2750
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002751static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002752
Guido van Rossum00d93061998-05-28 23:06:38 +00002753typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002754 PyObject_HEAD
2755 Tcl_TimerToken token;
2756 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002757} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002758
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002759/*[clinic input]
2760_tkinter.tktimertoken.deletetimerhandler
2761
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002762[clinic start generated code]*/
2763
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002764static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002765_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002766/*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002767{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002768 TkttObject *v = self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002769 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002770
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002771 if (v->token != NULL) {
2772 Tcl_DeleteTimerHandler(v->token);
2773 v->token = NULL;
2774 }
2775 if (func != NULL) {
2776 v->func = NULL;
2777 Py_DECREF(func);
2778 Py_DECREF(v); /* See Tktt_New() */
2779 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002780 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002781}
2782
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002783static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002784Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002785{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002786 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002787
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002788 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002789 if (v == NULL)
2790 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002791 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002792
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002793 Py_INCREF(func);
2794 v->token = NULL;
2795 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002796
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002797 /* Extra reference, deleted when called or when handler is deleted */
2798 Py_INCREF(v);
2799 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002800}
2801
2802static void
Fred Drake509d79a2000-07-08 04:04:38 +00002803Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002804{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002805 TkttObject *v = (TkttObject *)self;
2806 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002807 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002808
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002809 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002810
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002811 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002812 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002813}
2814
Guido van Rossum597ac201998-05-12 14:36:19 +00002815static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002816Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002817{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002818 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002819 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2820 v,
2821 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002822}
2823
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002824/** Timer Handler **/
2825
2826static void
Fred Drake509d79a2000-07-08 04:04:38 +00002827TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002828{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002829 TkttObject *v = (TkttObject *)clientData;
2830 PyObject *func = v->func;
2831 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002832
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002833 if (func == NULL)
2834 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002835
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002836 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002837
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002838 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002839
INADA Naoki72dccde2017-02-16 09:26:01 +09002840 res = _PyObject_CallNoArg(func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002841 Py_DECREF(func);
2842 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002844 if (res == NULL) {
2845 errorInCmd = 1;
2846 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2847 }
2848 else
2849 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002850
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002851 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002852}
2853
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002854/*[clinic input]
2855_tkinter.tkapp.createtimerhandler
2856
2857 milliseconds: int
2858 func: object
2859 /
2860
2861[clinic start generated code]*/
2862
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002863static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002864_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2865 PyObject *func)
2866/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002867{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002868 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002869
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002870 if (!PyCallable_Check(func)) {
2871 PyErr_SetString(PyExc_TypeError, "bad argument list");
2872 return NULL;
2873 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002874
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002875 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002876
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002877 v = Tktt_New(func);
2878 if (v) {
2879 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2880 (ClientData)v);
2881 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002882
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002883 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002884}
2885
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002886
Guido van Rossum18468821994-06-20 07:49:28 +00002887/** Event Loop **/
2888
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002889/*[clinic input]
2890_tkinter.tkapp.mainloop
2891
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002892 threshold: int = 0
2893 /
2894
2895[clinic start generated code]*/
2896
Guido van Rossum18468821994-06-20 07:49:28 +00002897static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002898_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03002899/*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002900{
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002901#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002902 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002903#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002904
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002905 CHECK_TCL_APPARTMENT;
2906 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002907
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002908 quitMainLoop = 0;
2909 while (Tk_GetNumMainWindows() > threshold &&
2910 !quitMainLoop &&
2911 !errorInCmd)
2912 {
2913 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002914
2915#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002916 if (self->threaded) {
2917 /* Allow other Python threads to run. */
2918 ENTER_TCL
2919 result = Tcl_DoOneEvent(0);
2920 LEAVE_TCL
2921 }
2922 else {
2923 Py_BEGIN_ALLOW_THREADS
2924 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2925 tcl_tstate = tstate;
2926 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2927 tcl_tstate = NULL;
2928 if(tcl_lock)PyThread_release_lock(tcl_lock);
2929 if (result == 0)
2930 Sleep(Tkinter_busywaitinterval);
2931 Py_END_ALLOW_THREADS
2932 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002933#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002934 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002935#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002936
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002937 if (PyErr_CheckSignals() != 0) {
2938 self->dispatching = 0;
2939 return NULL;
2940 }
2941 if (result < 0)
2942 break;
2943 }
2944 self->dispatching = 0;
2945 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002946
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002947 if (errorInCmd) {
2948 errorInCmd = 0;
2949 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2950 excInCmd = valInCmd = trbInCmd = NULL;
2951 return NULL;
2952 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002953 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002954}
2955
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002956/*[clinic input]
2957_tkinter.tkapp.dooneevent
Guido van Rossum062cfb01995-01-10 17:42:51 +00002958
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002959 flags: int = 0
2960 /
2961
2962[clinic start generated code]*/
2963
2964static PyObject *
2965_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2966/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2967{
2968 int rv;
Barry Warsawfa701a81997-01-16 00:15:11 +00002969
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002970 ENTER_TCL
2971 rv = Tcl_DoOneEvent(flags);
2972 LEAVE_TCL
Serhiy Storchaka8d0f6202015-05-06 14:19:22 +03002973 return PyLong_FromLong(rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002974}
2975
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002976/*[clinic input]
2977_tkinter.tkapp.quit
2978[clinic start generated code]*/
2979
Guido van Rossum062cfb01995-01-10 17:42:51 +00002980static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002981_tkinter_tkapp_quit_impl(TkappObject *self)
2982/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
Guido van Rossum18468821994-06-20 07:49:28 +00002983{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002984 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002985 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002986}
2987
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002988/*[clinic input]
2989_tkinter.tkapp.interpaddr
2990[clinic start generated code]*/
2991
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002992static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002993_tkinter_tkapp_interpaddr_impl(TkappObject *self)
2994/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002995{
Victor Stinnere1040e22013-09-05 00:22:24 +02002996 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002997}
2998
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03002999/*[clinic input]
3000_tkinter.tkapp.loadtk
3001[clinic start generated code]*/
3002
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003003static PyObject *
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003004_tkinter_tkapp_loadtk_impl(TkappObject *self)
3005/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
David Aschere2b4b322004-02-18 05:59:53 +00003006{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003007 Tcl_Interp *interp = Tkapp_Interp(self);
3008 const char * _tk_exists = NULL;
3009 int err;
David Aschere2b4b322004-02-18 05:59:53 +00003010
Guilherme Polob681df42009-02-09 22:33:59 +00003011#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003012 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
3013 * first call failed.
3014 * To avoid the deadlock, we just refuse the second call through
3015 * a static variable.
3016 */
3017 if (tk_load_failed) {
3018 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
3019 return NULL;
3020 }
Guilherme Polob681df42009-02-09 22:33:59 +00003021#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003022
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003023 /* We want to guard against calling Tk_Init() multiple times */
3024 CHECK_TCL_APPARTMENT;
3025 ENTER_TCL
3026 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
3027 ENTER_OVERLAP
3028 if (err == TCL_ERROR) {
3029 /* This sets an exception, but we cannot return right
3030 away because we need to exit the overlap first. */
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003031 Tkinter_Error((PyObject *)self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003032 } else {
3033 _tk_exists = Tkapp_Result(self);
3034 }
3035 LEAVE_OVERLAP_TCL
3036 if (err == TCL_ERROR) {
3037 return NULL;
3038 }
3039 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
3040 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003041 PyErr_SetString(Tkinter_TclError,
3042 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00003043#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003044 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00003045#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003046 return NULL;
3047 }
3048 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003049 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00003050}
Barry Warsawfa701a81997-01-16 00:15:11 +00003051
Martin v. Löwisffad6332002-11-26 09:28:05 +00003052static PyObject *
3053Tkapp_WantObjects(PyObject *self, PyObject *args)
3054{
3055
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003056 int wantobjects = -1;
3057 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3058 return NULL;
3059 if (wantobjects == -1)
3060 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3061 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003062
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003063 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003064}
3065
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003066/*[clinic input]
3067_tkinter.tkapp.willdispatch
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003068
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003069[clinic start generated code]*/
3070
3071static PyObject *
3072_tkinter_tkapp_willdispatch_impl(TkappObject *self)
Serhiy Storchaka7a9579c2016-05-02 13:45:20 +03003073/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003074{
3075 self->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003076
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003077 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003078}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003079
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003080
Guido van Rossum18468821994-06-20 07:49:28 +00003081/**** Tkapp Type Methods ****/
3082
3083static void
Fred Drake509d79a2000-07-08 04:04:38 +00003084Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003085{
Antoine Pitrou584e8152013-08-11 00:22:30 +02003086 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003087 /*CHECK_TCL_APPARTMENT;*/
3088 ENTER_TCL
3089 Tcl_DeleteInterp(Tkapp_Interp(self));
3090 LEAVE_TCL
3091 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02003092 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003093 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003094}
3095
Barry Warsawfa701a81997-01-16 00:15:11 +00003096
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003097
Guido van Rossum18468821994-06-20 07:49:28 +00003098/**** Tkinter Module ****/
3099
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003100typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003101 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003102 Py_ssize_t size; /* current size */
3103 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003104} FlattenContext;
3105
3106static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003107_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003108{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003109 /* expand tuple to hold (at least) size new items.
3110 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003111
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003112 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003113
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003114 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003115 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003116
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003117 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003118
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003119 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003120}
3121
3122static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003123_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003124{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003125 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003126
Serhiy Storchaka26861b02015-02-16 20:52:17 +02003127 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003128
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003129 if (depth > 1000) {
3130 PyErr_SetString(PyExc_ValueError,
3131 "nesting too deep in _flatten");
3132 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003133 } else if (PyTuple_Check(item) || PyList_Check(item)) {
3134 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003135 /* preallocate (assume no nesting) */
3136 if (context->size + size > context->maxsize &&
3137 !_bump(context, size))
3138 return 0;
3139 /* copy items to output tuple */
3140 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03003141 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003142 if (PyList_Check(o) || PyTuple_Check(o)) {
3143 if (!_flatten1(context, o, depth + 1))
3144 return 0;
3145 } else if (o != Py_None) {
3146 if (context->size + 1 > context->maxsize &&
3147 !_bump(context, 1))
3148 return 0;
3149 Py_INCREF(o);
3150 PyTuple_SET_ITEM(context->tuple,
3151 context->size++, o);
3152 }
3153 }
3154 } else {
3155 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3156 return 0;
3157 }
3158 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003159}
3160
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003161/*[clinic input]
3162_tkinter._flatten
3163
3164 item: object
3165 /
3166
3167[clinic start generated code]*/
3168
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003169static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003170_tkinter__flatten(PyObject *module, PyObject *item)
3171/*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003172{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003173 FlattenContext context;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003174
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003175 context.maxsize = PySequence_Size(item);
3176 if (context.maxsize < 0)
3177 return NULL;
3178 if (context.maxsize == 0)
3179 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003180
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003181 context.tuple = PyTuple_New(context.maxsize);
3182 if (!context.tuple)
3183 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003184
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003185 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003186
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003187 if (!_flatten1(&context, item,0))
3188 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003189
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003190 if (_PyTuple_Resize(&context.tuple, context.size))
3191 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003192
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003193 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003194}
3195
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003196/*[clinic input]
3197_tkinter.create
3198
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003199 screenName: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003200 baseName: str = NULL
3201 className: str = "Tk"
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003202 interactive: bool(accept={int}) = False
3203 wantobjects: bool(accept={int}) = False
3204 wantTk: bool(accept={int}) = True
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003205 if false, then Tk_Init() doesn't get called
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003206 sync: bool(accept={int}) = False
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003207 if true, then pass -sync to wish
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003208 use: str(accept={str, NoneType}) = NULL
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003209 if not None, then pass -use to wish
3210 /
3211
3212[clinic start generated code]*/
3213
Guido van Rossum18468821994-06-20 07:49:28 +00003214static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003215_tkinter_create_impl(PyObject *module, const char *screenName,
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003216 const char *baseName, const char *className,
3217 int interactive, int wantobjects, int wantTk, int sync,
3218 const char *use)
Serhiy Storchaka202fda52017-03-12 10:10:47 +02003219/*[clinic end generated code: output=e3315607648e6bb4 input=431907c134c80085]*/
Guido van Rossum18468821994-06-20 07:49:28 +00003220{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003221 /* XXX baseName is not used anymore;
3222 * try getting rid of it. */
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003223 CHECK_STRING_LENGTH(screenName);
3224 CHECK_STRING_LENGTH(baseName);
3225 CHECK_STRING_LENGTH(className);
3226 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003227
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003228 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003229 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003230 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003231}
3232
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003233/*[clinic input]
3234_tkinter.setbusywaitinterval
3235
3236 new_val: int
3237 /
3238
3239Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3240
3241It should be set to a divisor of the maximum time between frames in an animation.
3242[clinic start generated code]*/
3243
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003244static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003245_tkinter_setbusywaitinterval_impl(PyObject *module, int new_val)
3246/*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003247{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003248 if (new_val < 0) {
3249 PyErr_SetString(PyExc_ValueError,
3250 "busywaitinterval must be >= 0");
3251 return NULL;
3252 }
3253 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003254 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003255}
3256
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003257/*[clinic input]
3258_tkinter.getbusywaitinterval -> int
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003259
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003260Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3261[clinic start generated code]*/
3262
3263static int
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03003264_tkinter_getbusywaitinterval_impl(PyObject *module)
3265/*[clinic end generated code: output=23b72d552001f5c7 input=a695878d2d576a84]*/
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003266{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003267 return Tkinter_busywaitinterval;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003268}
3269
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003270#include "clinic/_tkinter.c.h"
3271
3272static PyMethodDef Tktt_methods[] =
3273{
3274 _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3275 {NULL, NULL}
3276};
3277
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003278static PyType_Slot Tktt_Type_slots[] = {
3279 {Py_tp_dealloc, Tktt_Dealloc},
3280 {Py_tp_repr, Tktt_Repr},
3281 {Py_tp_methods, Tktt_methods},
3282 {0, 0}
3283};
3284
3285static PyType_Spec Tktt_Type_spec = {
3286 "_tkinter.tktimertoken",
3287 sizeof(TkttObject),
3288 0,
3289 Py_TPFLAGS_DEFAULT,
3290 Tktt_Type_slots,
3291};
3292
3293
3294/**** Tkapp Method List ****/
3295
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003296static PyMethodDef Tkapp_methods[] =
3297{
3298 _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3299 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3300 {"call", Tkapp_Call, METH_VARARGS},
3301 _TKINTER_TKAPP_EVAL_METHODDEF
3302 _TKINTER_TKAPP_EVALFILE_METHODDEF
3303 _TKINTER_TKAPP_RECORD_METHODDEF
3304 _TKINTER_TKAPP_ADDERRINFO_METHODDEF
3305 {"setvar", Tkapp_SetVar, METH_VARARGS},
3306 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3307 {"getvar", Tkapp_GetVar, METH_VARARGS},
3308 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3309 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3310 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3311 _TKINTER_TKAPP_GETINT_METHODDEF
3312 _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3313 _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3314 _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3315 _TKINTER_TKAPP_EXPRLONG_METHODDEF
3316 _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3317 _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3318 _TKINTER_TKAPP_SPLITLIST_METHODDEF
3319 _TKINTER_TKAPP_SPLIT_METHODDEF
3320 _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3321 _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3322 _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3323 _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3324 _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3325 _TKINTER_TKAPP_MAINLOOP_METHODDEF
3326 _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3327 _TKINTER_TKAPP_QUIT_METHODDEF
3328 _TKINTER_TKAPP_INTERPADDR_METHODDEF
3329 _TKINTER_TKAPP_LOADTK_METHODDEF
3330 {NULL, NULL}
3331};
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003332
Larry Hastings2d0a69a2015-05-03 14:49:19 -07003333static PyType_Slot Tkapp_Type_slots[] = {
3334 {Py_tp_dealloc, Tkapp_Dealloc},
3335 {Py_tp_methods, Tkapp_methods},
3336 {0, 0}
3337};
3338
3339
3340static PyType_Spec Tkapp_Type_spec = {
3341 "_tkinter.tkapp",
3342 sizeof(TkappObject),
3343 0,
3344 Py_TPFLAGS_DEFAULT,
3345 Tkapp_Type_slots,
3346};
3347
Guido van Rossum18468821994-06-20 07:49:28 +00003348static PyMethodDef moduleMethods[] =
3349{
Serhiy Storchaka5abdf4842015-05-03 15:49:47 +03003350 _TKINTER__FLATTEN_METHODDEF
3351 _TKINTER_CREATE_METHODDEF
3352 _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3353 _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003354 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003355};
3356
Guido van Rossum7bf15641998-05-22 18:28:17 +00003357#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003358
3359static int stdin_ready = 0;
3360
Guido van Rossumad4db171998-06-13 13:56:28 +00003361#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003362static void
Fred Drake509d79a2000-07-08 04:04:38 +00003363MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003364{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003365 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003366}
Guido van Rossumad4db171998-06-13 13:56:28 +00003367#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003368
Martin v. Löwisa9656492003-03-30 08:44:58 +00003369#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003370static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003371#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003372
Guido van Rossum18468821994-06-20 07:49:28 +00003373static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003374EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003375{
Guido van Rossumad4db171998-06-13 13:56:28 +00003376#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003377 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003378#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003379#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003380 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003381#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003382 stdin_ready = 0;
3383 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003384#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003385 tfile = fileno(stdin);
3386 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003387#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003388 while (!errorInCmd && !stdin_ready) {
3389 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003390#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003391 if (_kbhit()) {
3392 stdin_ready = 1;
3393 break;
3394 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003395#endif
3396#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003397 Py_BEGIN_ALLOW_THREADS
3398 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3399 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003401 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003403 tcl_tstate = NULL;
3404 if(tcl_lock)PyThread_release_lock(tcl_lock);
3405 if (result == 0)
3406 Sleep(Tkinter_busywaitinterval);
3407 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003408#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003409 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003410#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003411
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003412 if (result < 0)
3413 break;
3414 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003415#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003416 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003417#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003418 if (errorInCmd) {
3419 errorInCmd = 0;
3420 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3421 excInCmd = valInCmd = trbInCmd = NULL;
3422 PyErr_Print();
3423 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003424#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003425 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003426#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003427 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003428}
Guido van Rossum18468821994-06-20 07:49:28 +00003429
Guido van Rossum00d93061998-05-28 23:06:38 +00003430#endif
3431
Guido van Rossum7bf15641998-05-22 18:28:17 +00003432static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003433EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003434{
Guido van Rossum00d93061998-05-28 23:06:38 +00003435#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003436 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003437#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003438 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003439#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003440 PyOS_InputHook = EventHook;
3441 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003442#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003443}
3444
3445static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003446DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003447{
Guido van Rossum00d93061998-05-28 23:06:38 +00003448#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003449 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3450 PyOS_InputHook = NULL;
3451 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003452#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003453}
3454
Barry Warsawfa701a81997-01-16 00:15:11 +00003455
Martin v. Löwis1a214512008-06-11 05:26:20 +00003456static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003457 PyModuleDef_HEAD_INIT,
3458 "_tkinter",
3459 NULL,
3460 -1,
3461 moduleMethods,
3462 NULL,
3463 NULL,
3464 NULL,
3465 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003466};
3467
Mark Hammond62b1ab12002-07-23 06:31:15 +00003468PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003469PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003470{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003471 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003472
Guido van Rossum00d93061998-05-28 23:06:38 +00003473#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003474 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003475 if (tcl_lock == NULL)
3476 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003477#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003478
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003479 m = PyModule_Create(&_tkintermodule);
3480 if (m == NULL)
3481 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003482
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003483 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3484 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003485 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003486 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003487 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003488 Py_INCREF(o);
3489 if (PyModule_AddObject(m, "TclError", o)) {
3490 Py_DECREF(o);
3491 Py_DECREF(m);
3492 return NULL;
3493 }
3494 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003495
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003496 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3497 Py_DECREF(m);
3498 return NULL;
3499 }
3500 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3501 Py_DECREF(m);
3502 return NULL;
3503 }
3504 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3505 Py_DECREF(m);
3506 return NULL;
3507 }
3508 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3509 Py_DECREF(m);
3510 return NULL;
3511 }
3512 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3513 Py_DECREF(m);
3514 return NULL;
3515 }
3516 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3517 Py_DECREF(m);
3518 return NULL;
3519 }
3520 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3521 Py_DECREF(m);
3522 return NULL;
3523 }
3524 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3525 Py_DECREF(m);
3526 return NULL;
3527 }
3528 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3529 Py_DECREF(m);
3530 return NULL;
3531 }
3532 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3533 Py_DECREF(m);
3534 return NULL;
3535 }
3536 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3537 Py_DECREF(m);
3538 return NULL;
3539 }
3540
3541 o = PyType_FromSpec(&Tkapp_Type_spec);
3542 if (o == NULL) {
3543 Py_DECREF(m);
3544 return NULL;
3545 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003546 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003547 if (PyModule_AddObject(m, "TkappType", o)) {
3548 Py_DECREF(o);
3549 Py_DECREF(m);
3550 return NULL;
3551 }
3552 Tkapp_Type = o;
3553
3554 o = PyType_FromSpec(&Tktt_Type_spec);
3555 if (o == NULL) {
3556 Py_DECREF(m);
3557 return NULL;
3558 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003559 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003560 if (PyModule_AddObject(m, "TkttType", o)) {
3561 Py_DECREF(o);
3562 Py_DECREF(m);
3563 return NULL;
3564 }
3565 Tktt_Type = o;
3566
3567 o = PyType_FromSpec(&PyTclObject_Type_spec);
3568 if (o == NULL) {
3569 Py_DECREF(m);
3570 return NULL;
3571 }
Serhiy Storchakae3f1b092016-05-08 20:46:22 +03003572 ((PyTypeObject *)o)->tp_new = NULL;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003573 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3574 Py_DECREF(o);
3575 Py_DECREF(m);
3576 return NULL;
3577 }
3578 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003579
3580#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003581 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3582 * start waking up. Note that Tcl_FindExecutable will do this, this
3583 * code must be above it! The original warning from
3584 * tkMacOSXAppInit.c is copied below.
3585 *
3586 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3587 * Tcl interpreter for now. It probably should work to do this
3588 * in the other order, but for now it doesn't seem to.
3589 *
3590 */
3591 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003592#endif
3593
3594
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003595 /* This helps the dynamic loader; in Unicode aware Tcl versions
3596 it also helps Tcl find its encodings. */
3597 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3598 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003599 cexe = PyUnicode_EncodeFSDefault(uexe);
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003600 if (cexe) {
3601#ifdef MS_WINDOWS
3602 int set_var = 0;
3603 PyObject *str_path;
3604 wchar_t *wcs_path;
3605 DWORD ret;
3606
3607 ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3608
3609 if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3610 str_path = _get_tcl_lib_path();
3611 if (str_path == NULL && PyErr_Occurred()) {
3612 return NULL;
3613 }
3614 if (str_path != NULL) {
3615 wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3616 if (wcs_path == NULL) {
3617 return NULL;
3618 }
3619 SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3620 set_var = 1;
3621 }
3622 }
3623
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003624 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003625
3626 if (set_var) {
3627 SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3628 PyMem_Free(wcs_path);
3629 }
3630#else
Serhiy Storchaka696c8af2016-06-19 11:22:47 +03003631 Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
Zachary Ware7dc9dea2015-05-22 11:36:53 -05003632#endif /* MS_WINDOWS */
3633 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003634 Py_XDECREF(cexe);
3635 Py_DECREF(uexe);
3636 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003637
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003638 if (PyErr_Occurred()) {
3639 Py_DECREF(m);
3640 return NULL;
3641 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003642
Guido van Rossum43ff8681998-07-14 18:02:13 +00003643#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003644 /* This was not a good idea; through <Destroy> bindings,
3645 Tcl_Finalize() may invoke Python code but at that point the
3646 interpreter and thread state have already been destroyed! */
3647 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003648#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003649 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003650}