blob: 4bced69682097f0fad62a7d8fe2dc932be63dc49 [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 Storchaka6716d602014-07-30 19:19:21 +030055#if TK_VERSION_HEX < 0x08040002
56#error "Tk older than 8.4 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000057#endif
58
Jack Janseneddc1442003-11-20 01:44:59 +000059#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000060#define HAVE_CREATEFILEHANDLER
61#endif
62
Guido van Rossum00d93061998-05-28 23:06:38 +000063#ifdef HAVE_CREATEFILEHANDLER
64
Neal Norwitzd948a432006-01-08 01:08:55 +000065/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
66 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
67#ifndef TCL_UNIX_FD
68# ifdef TCL_WIN_SOCKET
69# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
70# else
71# define TCL_UNIX_FD 1
72# endif
73#endif
74
Guido van Rossum00d93061998-05-28 23:06:38 +000075/* Tcl_CreateFileHandler() changed several times; these macros deal with the
76 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
77 Unix, only because Jack added it back); when available on Windows, it only
78 applies to sockets. */
79
Guido van Rossum7bf15641998-05-22 18:28:17 +000080#ifdef MS_WINDOWS
81#define FHANDLETYPE TCL_WIN_SOCKET
82#else
83#define FHANDLETYPE TCL_UNIX_FD
84#endif
85
Guido van Rossum00d93061998-05-28 23:06:38 +000086/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
87 which uses this to handle Tcl events while the user is typing commands. */
88
89#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +000090#define WAIT_FOR_STDIN
91#endif
92
Guido van Rossum00d93061998-05-28 23:06:38 +000093#endif /* HAVE_CREATEFILEHANDLER */
94
Guido van Rossumad4db171998-06-13 13:56:28 +000095#ifdef MS_WINDOWS
96#include <conio.h>
97#define WAIT_FOR_STDIN
98#endif
99
Guido van Rossum00d93061998-05-28 23:06:38 +0000100#ifdef WITH_THREAD
101
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000102/* The threading situation is complicated. Tcl is not thread-safe, except
103 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000104
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300105 So we need to use a lock around all uses of Tcl. Previously, the
106 Python interpreter lock was used for this. However, this causes
107 problems when other Python threads need to run while Tcl is blocked
108 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000109
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300110 To solve this problem, a separate lock for Tcl is introduced.
111 Holding it is incompatible with holding Python's interpreter lock.
112 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000113
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300114 ENTER_TCL and LEAVE_TCL are brackets, just like
115 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
116 used whenever a call into Tcl is made that could call an event
117 handler, or otherwise affect the state of a Tcl interpreter. These
118 assume that the surrounding code has the Python interpreter lock;
119 inside the brackets, the Python interpreter lock has been released
120 and the lock for Tcl has been acquired.
121
122 Sometimes, it is necessary to have both the Python lock and the Tcl
123 lock. (For example, when transferring data from the Tcl
124 interpreter result to a Python string object.) This can be done by
125 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
126 reacquires the Python lock (and restores the thread state) but
127 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
128 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000129
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000130 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300131 handlers when the handler needs to use Python. Such event handlers
132 are entered while the lock for Tcl is held; the event handler
133 presumably needs to use Python. ENTER_PYTHON releases the lock for
134 Tcl and acquires the Python interpreter lock, restoring the
135 appropriate thread state, and LEAVE_PYTHON releases the Python
136 interpreter lock and re-acquires the lock for Tcl. It is okay for
137 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
138 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000139
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300140 These locks expand to several statements and brackets; they should
141 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000142
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300143 If Tcl is threaded, this approach won't work anymore. The Tcl
144 interpreter is only valid in the thread that created it, and all Tk
145 activity must happen in this thread, also. That means that the
146 mainloop must be invoked in the thread that created the
147 interpreter. Invoking commands from other threads is possible;
148 _tkinter will queue an event for the interpreter thread, which will
149 then execute the command and pass back the result. If the main
150 thread is not in the mainloop, and invoking commands causes an
151 exception; if the main loop is running but not processing events,
152 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000153
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300154 In addition, for a threaded Tcl, a single global tcl_tstate won't
155 be sufficient anymore, since multiple Tcl interpreters may
156 simultaneously dispatch in different threads. So we use the Tcl TLS
157 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000158
Guido van Rossum00d93061998-05-28 23:06:38 +0000159*/
160
Guido van Rossum65d5b571998-12-21 19:32:43 +0000161static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000162
163#ifdef TCL_THREADS
164static Tcl_ThreadDataKey state_key;
165typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300166#define tcl_tstate \
167 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000168#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000169static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000170#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000171
172#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000173 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
174 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000175
176#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300177 tcl_tstate = NULL; \
178 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000179
Guido van Rossum62320c91998-06-15 04:36:09 +0000180#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000182
183#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000184 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000185
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000186#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000187 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300188 if(tcl_lock) \
189 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000190
191#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000192 { PyThreadState *tstate = PyEval_SaveThread(); \
193 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000194
195#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000196 if (((TkappObject *)self)->threaded && \
197 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300198 PyErr_SetString(PyExc_RuntimeError, \
199 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000200 return 0; \
201 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
203#else
204
205#define ENTER_TCL
206#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000207#define ENTER_OVERLAP
208#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000209#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000210#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000211#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000212
213#endif
214
Guido van Rossum97867b21996-08-08 19:09:53 +0000215#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000216#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000217#endif
218
Guido van Rossum18468821994-06-20 07:49:28 +0000219/**** Tkapp Object Declaration ****/
220
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300221static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000222
Guido van Rossum00d93061998-05-28 23:06:38 +0000223typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000224 PyObject_HEAD
225 Tcl_Interp *interp;
226 int wantobjects;
227 int threaded; /* True if tcl_platform[threaded] */
228 Tcl_ThreadId thread_id;
229 int dispatching;
230 /* We cannot include tclInt.h, as this is internal.
231 So we cache interesting types here. */
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200232 const Tcl_ObjType *OldBooleanType;
Zachary Ware037605b2014-08-05 11:54:34 -0500233 const Tcl_ObjType *BooleanType;
234 const Tcl_ObjType *ByteArrayType;
235 const Tcl_ObjType *DoubleType;
236 const Tcl_ObjType *IntType;
237 const Tcl_ObjType *ListType;
238 const Tcl_ObjType *ProcBodyType;
239 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000240} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000241
Guido van Rossum18468821994-06-20 07:49:28 +0000242#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000243#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000244
Guido van Rossum35d43371997-08-02 00:09:09 +0000245#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000246(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000247
Barry Warsawfa701a81997-01-16 00:15:11 +0000248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000249
Guido van Rossum18468821994-06-20 07:49:28 +0000250/**** Error Handling ****/
251
252static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000253static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000254static int errorInCmd = 0;
255static PyObject *excInCmd;
256static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000257static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000258
Guilherme Polob681df42009-02-09 22:33:59 +0000259#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000260static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000261#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000262
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000263
Guido van Rossum18468821994-06-20 07:49:28 +0000264static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000265Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000266{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000267 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
268 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000269}
270
Barry Warsawfa701a81997-01-16 00:15:11 +0000271
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000272
Guido van Rossum18468821994-06-20 07:49:28 +0000273/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000274
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000275static int Tkinter_busywaitinterval = 20;
276
Guido van Rossum00d93061998-05-28 23:06:38 +0000277#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000278#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000279
Guido van Rossum00d93061998-05-28 23:06:38 +0000280/* Millisecond sleep() for Unix platforms. */
281
282static void
Fred Drake509d79a2000-07-08 04:04:38 +0000283Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000284{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000285 /* XXX Too bad if you don't have select(). */
286 struct timeval t;
287 t.tv_sec = milli/1000;
288 t.tv_usec = (milli%1000) * 1000;
289 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000290}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000291#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000292
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000293/* Wait up to 1s for the mainloop to come up. */
294
295static int
296WaitForMainloop(TkappObject* self)
297{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000298 int i;
299 for (i = 0; i < 10; i++) {
300 if (self->dispatching)
301 return 1;
302 Py_BEGIN_ALLOW_THREADS
303 Sleep(100);
304 Py_END_ALLOW_THREADS
305 }
306 if (self->dispatching)
307 return 1;
308 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
309 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000310}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000311#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000314
Guido van Rossum18468821994-06-20 07:49:28 +0000315#define ARGSZ 64
316
Barry Warsawfa701a81997-01-16 00:15:11 +0000317
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000318
Guido van Rossum18468821994-06-20 07:49:28 +0000319static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200320unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
321{
322 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
323 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
324 /* Tcl encodes null character as \xc0\x80 */
325 if (memchr(s, '\xc0', size)) {
326 char *buf, *q;
327 const char *e = s + size;
328 PyErr_Clear();
329 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300330 if (buf == NULL) {
331 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200332 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300333 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200334 while (s != e) {
335 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
336 *q++ = '\0';
337 s += 2;
338 }
339 else
340 *q++ = *s++;
341 }
342 s = buf;
343 size = q - s;
344 r = PyUnicode_DecodeUTF8(s, size, NULL);
345 PyMem_Free(buf);
346 }
347 }
348 return r;
349}
350
351static PyObject *
352unicodeFromTclString(const char *s)
353{
354 return unicodeFromTclStringAndSize(s, strlen(s));
355}
356
357static PyObject *
358unicodeFromTclObj(Tcl_Obj *value)
359{
360 int len;
361 char *s = Tcl_GetStringFromObj(value, &len);
362 return unicodeFromTclStringAndSize(s, len);
363}
364
365
366static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300367Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000368{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000369 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300370 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000371 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300374 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000375 }
Guido van Rossum18468821994-06-20 07:49:28 +0000376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000377 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
378 /* Not a list.
379 * Could be a quoted string containing funnies, e.g. {"}.
380 * Return the string itself.
381 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200382 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000383 }
Guido van Rossum18468821994-06-20 07:49:28 +0000384
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000385 if (argc == 0)
386 v = PyUnicode_FromString("");
387 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200388 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000389 else if ((v = PyTuple_New(argc)) != NULL) {
390 int i;
391 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000393 for (i = 0; i < argc; i++) {
394 if ((w = Split(argv[i])) == NULL) {
395 Py_DECREF(v);
396 v = NULL;
397 break;
398 }
399 PyTuple_SetItem(v, i, w);
400 }
401 }
402 Tcl_Free(FREECAST argv);
403 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000404}
405
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300406/* In some cases, Tcl will still return strings that are supposed to
407 be lists. SplitObj walks through a nested tuple, finding string
408 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000409
Martin v. Löwis59683e82008-06-13 07:50:45 +0000410static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000411SplitObj(PyObject *arg)
412{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000413 if (PyTuple_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200414 Py_ssize_t i, size;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000415 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000416
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000417 size = PyTuple_Size(arg);
418 result = NULL;
419 /* Recursively invoke SplitObj for all tuple items.
420 If this does not return a new object, no action is
421 needed. */
422 for(i = 0; i < size; i++) {
423 elem = PyTuple_GetItem(arg, i);
424 newelem = SplitObj(elem);
425 if (!newelem) {
426 Py_XDECREF(result);
427 return NULL;
428 }
429 if (!result) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200430 Py_ssize_t k;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000431 if (newelem == elem) {
432 Py_DECREF(newelem);
433 continue;
434 }
435 result = PyTuple_New(size);
436 if (!result)
437 return NULL;
438 for(k = 0; k < i; k++) {
439 elem = PyTuple_GetItem(arg, k);
440 Py_INCREF(elem);
441 PyTuple_SetItem(result, k, elem);
442 }
443 }
444 PyTuple_SetItem(result, i, newelem);
445 }
446 if (result)
447 return result;
448 /* Fall through, returning arg. */
449 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300450 else if (PyList_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200451 Py_ssize_t i, size;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300452 PyObject *elem, *newelem, *result;
453
454 size = PyList_GET_SIZE(arg);
455 result = PyTuple_New(size);
456 if (!result)
457 return NULL;
458 /* Recursively invoke SplitObj for all list items. */
459 for(i = 0; i < size; i++) {
460 elem = PyList_GET_ITEM(arg, i);
461 newelem = SplitObj(elem);
462 if (!newelem) {
463 Py_XDECREF(result);
464 return NULL;
465 }
466 PyTuple_SetItem(result, i, newelem);
467 }
468 return result;
469 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300470 else if (PyUnicode_Check(arg)) {
471 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300472 const char **argv;
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300473 char *list = PyUnicode_AsUTF8(arg);
474
475 if (list == NULL ||
476 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
477 Py_INCREF(arg);
478 return arg;
479 }
480 Tcl_Free(FREECAST argv);
481 if (argc > 1)
482 return Split(list);
483 /* Fall through, returning arg. */
484 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000485 else if (PyBytes_Check(arg)) {
486 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300487 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000488 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
491 Py_INCREF(arg);
492 return arg;
493 }
494 Tcl_Free(FREECAST argv);
495 if (argc > 1)
496 return Split(PyBytes_AsString(arg));
497 /* Fall through, returning arg. */
498 }
499 Py_INCREF(arg);
500 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000501}
Barry Warsawfa701a81997-01-16 00:15:11 +0000502
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000503
Guido van Rossum18468821994-06-20 07:49:28 +0000504/**** Tkapp Object ****/
505
506#ifndef WITH_APPINIT
507int
Fred Drake509d79a2000-07-08 04:04:38 +0000508Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000509{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000512 if (Tcl_Init(interp) == TCL_ERROR) {
513 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
514 return TCL_ERROR;
515 }
Guilherme Polob681df42009-02-09 22:33:59 +0000516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000517 _tkinter_skip_tk_init = Tcl_GetVar(interp,
518 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
519 if (_tkinter_skip_tk_init != NULL &&
520 strcmp(_tkinter_skip_tk_init, "1") == 0) {
521 return TCL_OK;
522 }
Guilherme Polob681df42009-02-09 22:33:59 +0000523
524#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000525 if (tk_load_failed) {
526 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
527 return TCL_ERROR;
528 }
Guilherme Polob681df42009-02-09 22:33:59 +0000529#endif
530
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000531 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000532#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000534#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000535 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
536 return TCL_ERROR;
537 }
Guilherme Polob681df42009-02-09 22:33:59 +0000538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000539 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000540}
541#endif /* !WITH_APPINIT */
542
Guido van Rossum18468821994-06-20 07:49:28 +0000543
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000544
Barry Warsawfa701a81997-01-16 00:15:11 +0000545
546/* Initialize the Tk application; see the `main' function in
547 * `tkMain.c'.
548 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000549
Thomas Wouters58d05102000-07-24 14:43:35 +0000550static void EnableEventHook(void); /* Forward */
551static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000552
Barry Warsawfa701a81997-01-16 00:15:11 +0000553static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300554Tkapp_New(const char *screenName, const char *className,
555 int interactive, int wantobjects, int wantTk, int sync,
556 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000557{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000558 TkappObject *v;
559 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000560
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300561 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 if (v == NULL)
563 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200564 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000565
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000566 v->interp = Tcl_CreateInterp();
567 v->wantobjects = wantobjects;
568 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
569 TCL_GLOBAL_ONLY) != NULL;
570 v->thread_id = Tcl_GetCurrentThread();
571 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000572
573#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000574 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300575 PyErr_SetString(PyExc_RuntimeError,
576 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000577 Py_DECREF(v);
578 return 0;
579 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000580#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000581#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000582 if (v->threaded && tcl_lock) {
583 /* If Tcl is threaded, we don't need the lock. */
584 PyThread_free_lock(tcl_lock);
585 tcl_lock = NULL;
586 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000587#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000588
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200589 v->OldBooleanType = Tcl_GetObjType("boolean");
590 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 v->ByteArrayType = Tcl_GetObjType("bytearray");
592 v->DoubleType = Tcl_GetObjType("double");
593 v->IntType = Tcl_GetObjType("int");
594 v->ListType = Tcl_GetObjType("list");
595 v->ProcBodyType = Tcl_GetObjType("procbody");
596 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 /* Delete the 'exit' command, which can screw things up */
599 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000601 if (screenName != NULL)
602 Tcl_SetVar2(v->interp, "env", "DISPLAY",
603 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000605 if (interactive)
606 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
607 else
608 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000609
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000610 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200611 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 if (!argv0) {
613 PyErr_NoMemory();
614 Py_DECREF(v);
615 return NULL;
616 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000617
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200619 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
620 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000621 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200622 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000623
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000624 if (! wantTk) {
625 Tcl_SetVar(v->interp,
626 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
627 }
Guilherme Polob681df42009-02-09 22:33:59 +0000628#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000629 else if (tk_load_failed) {
630 Tcl_SetVar(v->interp,
631 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
632 }
Guilherme Polob681df42009-02-09 22:33:59 +0000633#endif
David Aschere2b4b322004-02-18 05:59:53 +0000634
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000635 /* some initial arguments need to be in argv */
636 if (sync || use) {
637 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200638 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000639
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000640 if (sync)
641 len += sizeof "-sync";
642 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200643 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000644
Victor Stinneree6c3c72014-09-11 17:50:21 +0200645 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000646 if (!args) {
647 PyErr_NoMemory();
648 Py_DECREF(v);
649 return NULL;
650 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000651
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000652 args[0] = '\0';
653 if (sync)
654 strcat(args, "-sync");
655 if (use) {
656 if (sync)
657 strcat(args, " ");
658 strcat(args, "-use ");
659 strcat(args, use);
660 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000661
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200663 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 if (Tcl_AppInit(v->interp) != TCL_OK) {
667 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000668#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000669 if (wantTk) {
670 const char *_tkinter_tk_failed;
671 _tkinter_tk_failed = Tcl_GetVar(v->interp,
672 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 if ( _tkinter_tk_failed != NULL &&
675 strcmp(_tkinter_tk_failed, "1") == 0) {
676 tk_load_failed = 1;
677 }
678 }
Guilherme Polob681df42009-02-09 22:33:59 +0000679#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000680 Py_DECREF((PyObject *)v);
681 return (TkappObject *)result;
682 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000685
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000686 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000687}
688
Barry Warsawfa701a81997-01-16 00:15:11 +0000689
Benjamin Peterson5879d412009-03-30 14:51:56 +0000690#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000691static void
692Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000693 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000694{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000695 Py_BEGIN_ALLOW_THREADS;
696 Tcl_MutexLock(mutex);
697 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
698 Tcl_ThreadAlert(self->thread_id);
699 Tcl_ConditionWait(cond, mutex, NULL);
700 Tcl_MutexUnlock(mutex);
701 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000702}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000703#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000704
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000705
Guido van Rossum18468821994-06-20 07:49:28 +0000706/** Tcl Eval **/
707
Martin v. Löwisffad6332002-11-26 09:28:05 +0000708typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000709 PyObject_HEAD
710 Tcl_Obj *value;
711 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000712} PyTclObject;
713
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300714static PyObject *PyTclObject_Type;
715#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000716
717static PyObject *
718newPyTclObject(Tcl_Obj *arg)
719{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300721 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000722 if (self == NULL)
723 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200724 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000725 Tcl_IncrRefCount(arg);
726 self->value = arg;
727 self->string = NULL;
728 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000729}
730
731static void
732PyTclObject_dealloc(PyTclObject *self)
733{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200734 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000735 Tcl_DecrRefCount(self->value);
736 Py_XDECREF(self->string);
737 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200738 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000739}
740
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000741static char*
742PyTclObject_TclString(PyObject *self)
743{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000744 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000745}
746
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000747/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000748PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000749"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000750
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000751static PyObject *
752PyTclObject_string(PyTclObject *self, void *ignored)
753{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200755 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000756 if (!self->string)
757 return NULL;
758 }
759 Py_INCREF(self->string);
760 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000761}
762
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000763static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000764PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000765{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200766 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000767 Py_INCREF(self->string);
768 return self->string;
769 }
770 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200771 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000772}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000773
Martin v. Löwisffad6332002-11-26 09:28:05 +0000774static PyObject *
775PyTclObject_repr(PyTclObject *self)
776{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300777 PyObject *repr, *str = PyTclObject_str(self, NULL);
778 if (str == NULL)
779 return NULL;
780 repr = PyUnicode_FromFormat("<%s object: %R>",
781 self->value->typePtr->name, str);
782 Py_DECREF(str);
783 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000784}
785
Mark Dickinson211c6252009-02-01 10:28:51 +0000786#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
787
788static PyObject *
789PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000790{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000791 int result;
792 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000793
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000794 /* neither argument should be NULL, unless something's gone wrong */
795 if (self == NULL || other == NULL) {
796 PyErr_BadInternalCall();
797 return NULL;
798 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000799
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000800 /* both arguments should be instances of PyTclObject */
801 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
802 v = Py_NotImplemented;
803 goto finished;
804 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000805
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000806 if (self == other)
807 /* fast path when self and other are identical */
808 result = 0;
809 else
810 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
811 Tcl_GetString(((PyTclObject *)other)->value));
812 /* Convert return value to a Boolean */
813 switch (op) {
814 case Py_EQ:
815 v = TEST_COND(result == 0);
816 break;
817 case Py_NE:
818 v = TEST_COND(result != 0);
819 break;
820 case Py_LE:
821 v = TEST_COND(result <= 0);
822 break;
823 case Py_GE:
824 v = TEST_COND(result >= 0);
825 break;
826 case Py_LT:
827 v = TEST_COND(result < 0);
828 break;
829 case Py_GT:
830 v = TEST_COND(result > 0);
831 break;
832 default:
833 PyErr_BadArgument();
834 return NULL;
835 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000836 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000837 Py_INCREF(v);
838 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000839}
840
Martin v. Löwis39195712003-01-04 00:33:13 +0000841PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
842
Martin v. Löwisffad6332002-11-26 09:28:05 +0000843static PyObject*
844get_typename(PyTclObject* obj, void* ignored)
845{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200846 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000847}
848
Martin v. Löwis39195712003-01-04 00:33:13 +0000849
Martin v. Löwisffad6332002-11-26 09:28:05 +0000850static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000851 {"typename", (getter)get_typename, NULL, get_typename__doc__},
852 {"string", (getter)PyTclObject_string, NULL,
853 PyTclObject_string__doc__},
854 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000855};
856
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300857static PyType_Slot PyTclObject_Type_slots[] = {
858 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
859 {Py_tp_repr, (reprfunc)PyTclObject_repr},
860 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200861 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300862 {Py_tp_richcompare, PyTclObject_richcompare},
863 {Py_tp_getset, PyTclObject_getsetlist},
864 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000865};
866
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300867static PyType_Spec PyTclObject_Type_spec = {
868 "_tkinter.Tcl_Obj",
869 sizeof(PyTclObject),
870 0,
871 Py_TPFLAGS_DEFAULT,
872 PyTclObject_Type_slots,
873};
874
875
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300876#if PY_SIZE_MAX > INT_MAX
877#define CHECK_STRING_LENGTH(s) do { \
878 if (s != NULL && strlen(s) >= INT_MAX) { \
879 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
880 return NULL; \
881 } } while(0)
882#else
883#define CHECK_STRING_LENGTH(s)
884#endif
885
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000886static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000887AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000888{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000889 Tcl_Obj *result;
890 long longVal;
891 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000892
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200893 if (PyBytes_Check(value)) {
894 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
895 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
896 return NULL;
897 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300898 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200899 (int)PyBytes_GET_SIZE(value));
900 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000901 else if (PyBool_Check(value))
902 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
903 else if (PyLong_CheckExact(value) &&
904 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
905 !overflow)) {
906 /* If there is an overflow in the long conversion,
907 fall through to default object handling. */
908 return Tcl_NewLongObj(longVal);
909 }
910 else if (PyFloat_Check(value))
911 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300912 else if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300913 Tcl_Obj **argv;
914 Py_ssize_t size, i;
915
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300916 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300917 if (size == 0)
918 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300919 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300920 PyErr_SetString(PyExc_OverflowError,
921 PyTuple_Check(value) ? "tuple is too long" :
922 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300923 return NULL;
924 }
Victor Stinneree6c3c72014-09-11 17:50:21 +0200925 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
926 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +0200927 PyErr_NoMemory();
928 return NULL;
929 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300930 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300931 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200932 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200933 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000934 return result;
935 }
936 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200937 void *inbuf;
938 Py_ssize_t size;
939 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000940 Tcl_UniChar *outbuf = NULL;
941 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200942 size_t allocsize;
943
944 if (PyUnicode_READY(value) == -1)
945 return NULL;
946
947 inbuf = PyUnicode_DATA(value);
948 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300949 if (size == 0)
950 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300951 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
952 PyErr_SetString(PyExc_OverflowError, "string is too long");
953 return NULL;
954 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200955 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200956 if (kind == sizeof(Tcl_UniChar))
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200957 return Tcl_NewUnicodeObj(inbuf, (int)size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200958 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200959 outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000960 /* Else overflow occurred, and we take the next exit */
961 if (!outbuf) {
962 PyErr_NoMemory();
963 return NULL;
964 }
965 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200966 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
967 /* We cannot test for sizeof(Tcl_UniChar) directly,
968 so we test for UTF-8 size instead. */
969#if TCL_UTF_MAX == 3
970 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000971 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200972 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100973 "character U+%x is above the range "
974 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100975 ch);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200976 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000977 return NULL;
978 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300979#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200980 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000981 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200982 result = Tcl_NewUnicodeObj(outbuf, (int)size);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200983 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000984 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000985 }
986 else if(PyTclObject_Check(value)) {
987 Tcl_Obj *v = ((PyTclObject*)value)->value;
988 Tcl_IncrRefCount(v);
989 return v;
990 }
991 else {
992 PyObject *v = PyObject_Str(value);
993 if (!v)
994 return 0;
995 result = AsObj(v);
996 Py_DECREF(v);
997 return result;
998 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000999}
1000
Martin v. Löwisffad6332002-11-26 09:28:05 +00001001static PyObject*
1002FromObj(PyObject* tkapp, Tcl_Obj *value)
1003{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001004 PyObject *result = NULL;
1005 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001006 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001008 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001009 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001010 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001011
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001012 if (value->typePtr == app->BooleanType ||
1013 value->typePtr == app->OldBooleanType) {
1014 int boolValue;
1015 if (Tcl_GetBooleanFromObj(interp, value, &boolValue) == TCL_ERROR)
1016 return Tkinter_Error(tkapp);
1017 return PyBool_FromLong(boolValue);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001018 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001019
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001020 if (value->typePtr == app->ByteArrayType) {
1021 int size;
1022 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1023 return PyBytes_FromStringAndSize(data, size);
1024 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001025
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001026 if (value->typePtr == app->DoubleType) {
1027 return PyFloat_FromDouble(value->internalRep.doubleValue);
1028 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001029
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001030 if (value->typePtr == app->IntType) {
1031 return PyLong_FromLong(value->internalRep.longValue);
1032 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001033
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001034 if (value->typePtr == app->ListType) {
1035 int size;
1036 int i, status;
1037 PyObject *elem;
1038 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001039
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001040 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001041 if (status == TCL_ERROR)
1042 return Tkinter_Error(tkapp);
1043 result = PyTuple_New(size);
1044 if (!result)
1045 return NULL;
1046 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001047 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001048 if (status == TCL_ERROR) {
1049 Py_DECREF(result);
1050 return Tkinter_Error(tkapp);
1051 }
1052 elem = FromObj(tkapp, tcl_elem);
1053 if (!elem) {
1054 Py_DECREF(result);
1055 return NULL;
1056 }
1057 PyTuple_SetItem(result, i, elem);
1058 }
1059 return result;
1060 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001061
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001062 if (value->typePtr == app->ProcBodyType) {
1063 /* fall through: return tcl object. */
1064 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001065
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001066 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001067 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001068 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001069 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001070 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001071
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001072 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001073}
1074
Benjamin Peterson5879d412009-03-30 14:51:56 +00001075#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001076/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001077TCL_DECLARE_MUTEX(call_mutex)
1078
1079typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001080 Tcl_Event ev; /* Must be first */
1081 TkappObject *self;
1082 PyObject *args;
1083 int flags;
1084 PyObject **res;
1085 PyObject **exc_type, **exc_value, **exc_tb;
1086 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001087} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001088#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001089
1090void
1091Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001092{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001093 int i;
1094 for (i = 0; i < objc; i++)
1095 Tcl_DecrRefCount(objv[i]);
1096 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001097 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001098}
Guido van Rossum18468821994-06-20 07:49:28 +00001099
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001100/* Convert Python objects to Tcl objects. This must happen in the
1101 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001102
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001103static Tcl_Obj**
1104Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1105{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001106 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001107 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001108 if (args == NULL)
1109 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001110
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001111 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001112 objv[0] = AsObj(args);
1113 if (objv[0] == 0)
1114 goto finally;
1115 objc = 1;
1116 Tcl_IncrRefCount(objv[0]);
1117 }
1118 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001119 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001120
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001121 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001122 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001123 PyErr_SetString(PyExc_OverflowError,
1124 PyTuple_Check(args) ? "tuple is too long" :
1125 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001126 return NULL;
1127 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001128 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001129 if (objv == NULL) {
1130 PyErr_NoMemory();
1131 objc = 0;
1132 goto finally;
1133 }
1134 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001135
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001136 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001137 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001138 if (v == Py_None) {
1139 objc = i;
1140 break;
1141 }
1142 objv[i] = AsObj(v);
1143 if (!objv[i]) {
1144 /* Reset objc, so it attempts to clear
1145 objects only up to i. */
1146 objc = i;
1147 goto finally;
1148 }
1149 Tcl_IncrRefCount(objv[i]);
1150 }
1151 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001152 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001153 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001154finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001155 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001156 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001157}
Guido van Rossum212643f1998-04-29 16:22:14 +00001158
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001159/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001160
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001161static PyObject*
1162Tkapp_CallResult(TkappObject *self)
1163{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001164 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001165 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001166 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001167 /* Not sure whether the IncrRef is necessary, but something
1168 may overwrite the interpreter result while we are
1169 converting it. */
1170 Tcl_IncrRefCount(value);
1171 res = FromObj((PyObject*)self, value);
1172 Tcl_DecrRefCount(value);
1173 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001174 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001175 }
1176 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001177}
Guido van Rossum632de272000-03-29 00:19:50 +00001178
Benjamin Peterson5879d412009-03-30 14:51:56 +00001179#ifdef WITH_THREAD
1180
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001181/* Tkapp_CallProc is the event procedure that is executed in the context of
1182 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1183 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001184
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001185static int
1186Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1187{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001188 Tcl_Obj *objStore[ARGSZ];
1189 Tcl_Obj **objv;
1190 int objc;
1191 int i;
1192 ENTER_PYTHON
1193 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1194 if (!objv) {
1195 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1196 *(e->res) = NULL;
1197 }
1198 LEAVE_PYTHON
1199 if (!objv)
1200 goto done;
1201 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1202 ENTER_PYTHON
1203 if (i == TCL_ERROR) {
1204 *(e->res) = NULL;
1205 *(e->exc_type) = NULL;
1206 *(e->exc_tb) = NULL;
1207 *(e->exc_value) = PyObject_CallFunction(
1208 Tkinter_TclError, "s",
1209 Tcl_GetStringResult(e->self->interp));
1210 }
1211 else {
1212 *(e->res) = Tkapp_CallResult(e->self);
1213 }
1214 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001215
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001216 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001217done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001218 /* Wake up calling thread. */
1219 Tcl_MutexLock(&call_mutex);
1220 Tcl_ConditionNotify(e->done);
1221 Tcl_MutexUnlock(&call_mutex);
1222 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001223}
1224
Benjamin Peterson5879d412009-03-30 14:51:56 +00001225#endif
1226
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001227/* This is the main entry point for calling a Tcl command.
1228 It supports three cases, with regard to threading:
1229 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1230 the context of the calling thread.
1231 2. Tcl is threaded, caller of the command is in the interpreter thread:
1232 Execute the command in the calling thread. Since the Tcl lock will
1233 not be used, we can merge that with case 1.
1234 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1235 the interpreter thread. Allocation of Tcl objects needs to occur in the
1236 interpreter thread, so we ship the PyObject* args to the target thread,
1237 and perform processing there. */
1238
1239static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001240Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001241{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001242 Tcl_Obj *objStore[ARGSZ];
1243 Tcl_Obj **objv = NULL;
1244 int objc, i;
1245 PyObject *res = NULL;
1246 TkappObject *self = (TkappObject*)selfptr;
1247 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001249 /* If args is a single tuple, replace with contents of tuple */
1250 if (1 == PyTuple_Size(args)){
1251 PyObject* item = PyTuple_GetItem(args, 0);
1252 if (PyTuple_Check(item))
1253 args = item;
1254 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001255#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001256 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1257 /* We cannot call the command directly. Instead, we must
1258 marshal the parameters to the interpreter thread. */
1259 Tkapp_CallEvent *ev;
1260 Tcl_Condition cond = NULL;
1261 PyObject *exc_type, *exc_value, *exc_tb;
1262 if (!WaitForMainloop(self))
1263 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001264 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1265 if (ev == NULL) {
1266 PyErr_NoMemory();
1267 return NULL;
1268 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001269 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1270 ev->self = self;
1271 ev->args = args;
1272 ev->res = &res;
1273 ev->exc_type = &exc_type;
1274 ev->exc_value = &exc_value;
1275 ev->exc_tb = &exc_tb;
1276 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001277
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001278 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001280 if (res == NULL) {
1281 if (exc_type)
1282 PyErr_Restore(exc_type, exc_value, exc_tb);
1283 else
1284 PyErr_SetObject(Tkinter_TclError, exc_value);
1285 }
1286 Tcl_ConditionFinalize(&cond);
1287 }
1288 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001289#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001290 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001291
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001292 objv = Tkapp_CallArgs(args, objStore, &objc);
1293 if (!objv)
1294 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001295
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001296 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001298 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001299
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001300 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001301
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001302 if (i == TCL_ERROR)
1303 Tkinter_Error(selfptr);
1304 else
1305 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001306
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001307 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001308
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001309 Tkapp_CallDeallocArgs(objv, objStore, objc);
1310 }
1311 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001312}
1313
1314
1315static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001316Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001317{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001318 char *script;
1319 PyObject *res = NULL;
1320 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001321
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001322 if (!PyArg_ParseTuple(args, "s:eval", &script))
1323 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001324
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001325 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001327
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001328 ENTER_TCL
1329 err = Tcl_Eval(Tkapp_Interp(self), script);
1330 ENTER_OVERLAP
1331 if (err == TCL_ERROR)
1332 res = Tkinter_Error(self);
1333 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001334 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001335 LEAVE_OVERLAP_TCL
1336 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001337}
1338
1339static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001340Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001341{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001342 char *fileName;
1343 PyObject *res = NULL;
1344 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001345
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1347 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001348
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001349 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 ENTER_TCL
1353 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1354 ENTER_OVERLAP
1355 if (err == TCL_ERROR)
1356 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001357 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001358 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001359 LEAVE_OVERLAP_TCL
1360 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001361}
1362
1363static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001364Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001365{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001366 char *script;
1367 PyObject *res = NULL;
1368 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001369
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001370 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001371 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001372
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001373 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001374 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001376 ENTER_TCL
1377 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1378 ENTER_OVERLAP
1379 if (err == TCL_ERROR)
1380 res = Tkinter_Error(self);
1381 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001382 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001383 LEAVE_OVERLAP_TCL
1384 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001385}
1386
1387static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001388Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001389{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001390 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001392 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1393 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001394 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001395 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001397 ENTER_TCL
1398 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1399 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001400
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001401 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001402}
1403
Barry Warsawfa701a81997-01-16 00:15:11 +00001404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001405
Guido van Rossum18468821994-06-20 07:49:28 +00001406/** Tcl Variable **/
1407
Benjamin Peterson5879d412009-03-30 14:51:56 +00001408typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1409
1410#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001411TCL_DECLARE_MUTEX(var_mutex)
1412
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001413typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001414 Tcl_Event ev; /* must be first */
1415 PyObject *self;
1416 PyObject *args;
1417 int flags;
1418 EventFunc func;
1419 PyObject **res;
1420 PyObject **exc_type;
1421 PyObject **exc_val;
1422 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001423} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001424#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001425
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001426static int
1427varname_converter(PyObject *in, void *_out)
1428{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001429 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001430 char **out = (char**)_out;
1431 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001432 if (PyBytes_Size(in) > INT_MAX) {
1433 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1434 return 0;
1435 }
1436 s = PyBytes_AsString(in);
Victor Stinner706768c2014-08-16 01:03:39 +02001437 if (strlen(s) != (size_t)PyBytes_Size(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001438 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001439 return 0;
1440 }
1441 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001442 return 1;
1443 }
1444 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001445 Py_ssize_t size;
1446 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001447 if (s == NULL) {
1448 return 0;
1449 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001450 if (size > INT_MAX) {
1451 PyErr_SetString(PyExc_OverflowError, "string is too long");
1452 return 0;
1453 }
Victor Stinner706768c2014-08-16 01:03:39 +02001454 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001455 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001456 return 0;
1457 }
1458 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001459 return 1;
1460 }
1461 if (PyTclObject_Check(in)) {
1462 *out = PyTclObject_TclString(in);
1463 return 1;
1464 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001465 PyErr_Format(PyExc_TypeError,
1466 "must be str, bytes or Tcl_Obj, not %.50s",
1467 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001468 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001469}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001470
Benjamin Peterson5879d412009-03-30 14:51:56 +00001471#ifdef WITH_THREAD
1472
Martin v. Löwis59683e82008-06-13 07:50:45 +00001473static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001474var_perform(VarEvent *ev)
1475{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001476 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1477 if (!*(ev->res)) {
1478 PyObject *exc, *val, *tb;
1479 PyErr_Fetch(&exc, &val, &tb);
1480 PyErr_NormalizeException(&exc, &val, &tb);
1481 *(ev->exc_type) = exc;
1482 *(ev->exc_val) = val;
1483 Py_DECREF(tb);
1484 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001485
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486}
1487
1488static int
1489var_proc(VarEvent* ev, int flags)
1490{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001491 ENTER_PYTHON
1492 var_perform(ev);
1493 Tcl_MutexLock(&var_mutex);
1494 Tcl_ConditionNotify(ev->cond);
1495 Tcl_MutexUnlock(&var_mutex);
1496 LEAVE_PYTHON
1497 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001498}
1499
Benjamin Peterson5879d412009-03-30 14:51:56 +00001500#endif
1501
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001502static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001503var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001504{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001505#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001506 TkappObject *self = (TkappObject*)selfptr;
1507 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001508 VarEvent *ev;
1509 PyObject *res, *exc_type, *exc_val;
1510 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001512 /* The current thread is not the interpreter thread. Marshal
1513 the call to the interpreter thread, then wait for
1514 completion. */
1515 if (!WaitForMainloop(self))
1516 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001517
Serhiy Storchaka07940882014-09-11 10:38:54 +03001518 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1519 if (ev == NULL) {
1520 PyErr_NoMemory();
1521 return NULL;
1522 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001523 ev->self = selfptr;
1524 ev->args = args;
1525 ev->flags = flags;
1526 ev->func = func;
1527 ev->res = &res;
1528 ev->exc_type = &exc_type;
1529 ev->exc_val = &exc_val;
1530 ev->cond = &cond;
1531 ev->ev.proc = (Tcl_EventProc*)var_proc;
1532 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1533 Tcl_ConditionFinalize(&cond);
1534 if (!res) {
1535 PyErr_SetObject(exc_type, exc_val);
1536 Py_DECREF(exc_type);
1537 Py_DECREF(exc_val);
1538 return NULL;
1539 }
1540 return res;
1541 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001542#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001543 /* Tcl is not threaded, or this is the interpreter thread. */
1544 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001545}
1546
Guido van Rossum18468821994-06-20 07:49:28 +00001547static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001548SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001549{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 char *name1, *name2;
1551 PyObject *newValue;
1552 PyObject *res = NULL;
1553 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001554
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001555 switch (PyTuple_GET_SIZE(args)) {
1556 case 2:
1557 if (!PyArg_ParseTuple(args, "O&O:setvar",
1558 varname_converter, &name1, &newValue))
1559 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001560 /* XXX Acquire tcl lock??? */
1561 newval = AsObj(newValue);
1562 if (newval == NULL)
1563 return NULL;
1564 ENTER_TCL
1565 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1566 newval, flags);
1567 ENTER_OVERLAP
1568 if (!ok)
1569 Tkinter_Error(self);
1570 else {
1571 res = Py_None;
1572 Py_INCREF(res);
1573 }
1574 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001575 break;
1576 case 3:
1577 if (!PyArg_ParseTuple(args, "ssO:setvar",
1578 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001579 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001580 CHECK_STRING_LENGTH(name1);
1581 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001582 /* XXX must hold tcl lock already??? */
1583 newval = AsObj(newValue);
1584 ENTER_TCL
1585 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1586 ENTER_OVERLAP
1587 if (!ok)
1588 Tkinter_Error(self);
1589 else {
1590 res = Py_None;
1591 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001592 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001593 LEAVE_OVERLAP_TCL
1594 break;
1595 default:
1596 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1597 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001598 }
1599 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001600}
1601
1602static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001603Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001604{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001605 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001606}
1607
1608static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001609Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001610{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001611 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001612}
1613
Barry Warsawfa701a81997-01-16 00:15:11 +00001614
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001615
Guido van Rossum18468821994-06-20 07:49:28 +00001616static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001617GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001618{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001619 char *name1, *name2=NULL;
1620 PyObject *res = NULL;
1621 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001622
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001623 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1624 varname_converter, &name1, &name2))
1625 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001626
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001627 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001628 ENTER_TCL
1629 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1630 ENTER_OVERLAP
1631 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001632 PyErr_SetString(Tkinter_TclError,
1633 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001634 } else {
1635 if (((TkappObject*)self)->wantobjects) {
1636 res = FromObj(self, tres);
1637 }
1638 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001639 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001640 }
1641 }
1642 LEAVE_OVERLAP_TCL
1643 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001644}
1645
1646static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001647Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001648{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001649 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001650}
1651
1652static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001653Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001654{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001655 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001656}
1657
Barry Warsawfa701a81997-01-16 00:15:11 +00001658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001659
Guido van Rossum18468821994-06-20 07:49:28 +00001660static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001661UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001662{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001663 char *name1, *name2=NULL;
1664 int code;
1665 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001667 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1668 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001669
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001670 CHECK_STRING_LENGTH(name1);
1671 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001672 ENTER_TCL
1673 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1674 ENTER_OVERLAP
1675 if (code == TCL_ERROR)
1676 res = Tkinter_Error(self);
1677 else {
1678 Py_INCREF(Py_None);
1679 res = Py_None;
1680 }
1681 LEAVE_OVERLAP_TCL
1682 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001683}
1684
1685static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001686Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001687{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001688 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001689}
1690
1691static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001692Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001693{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001694 return var_invoke(UnsetVar, self, args,
1695 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001696}
1697
Barry Warsawfa701a81997-01-16 00:15:11 +00001698
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001699
Guido van Rossum18468821994-06-20 07:49:28 +00001700/** Tcl to Python **/
1701
1702static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001703Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001704{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001705 char *s;
1706 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001707
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001708 if (PyTuple_Size(args) == 1) {
1709 PyObject* o = PyTuple_GetItem(args, 0);
1710 if (PyLong_Check(o)) {
1711 Py_INCREF(o);
1712 return o;
1713 }
1714 }
1715 if (!PyArg_ParseTuple(args, "s:getint", &s))
1716 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001717 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001718 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1719 return Tkinter_Error(self);
1720 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001721}
1722
1723static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001724Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001725{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001726 char *s;
1727 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001728
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001729 if (PyTuple_Size(args) == 1) {
1730 PyObject *o = PyTuple_GetItem(args, 0);
1731 if (PyFloat_Check(o)) {
1732 Py_INCREF(o);
1733 return o;
1734 }
1735 }
1736 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1737 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001738 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001739 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1740 return Tkinter_Error(self);
1741 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001742}
1743
1744static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001745Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001746{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001747 char *s;
1748 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001749
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001750 if (PyTuple_Size(args) == 1) {
1751 PyObject *o = PyTuple_GetItem(args, 0);
1752 if (PyLong_Check(o)) {
1753 Py_INCREF(o);
1754 return o;
1755 }
1756 }
1757 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1758 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001759 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001760 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1761 return Tkinter_Error(self);
1762 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001763}
1764
1765static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001766Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001767{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001768 char *s;
1769 PyObject *res = NULL;
1770 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001771
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001772 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1773 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001774
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001775 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001776 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001777
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001778 ENTER_TCL
1779 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1780 ENTER_OVERLAP
1781 if (retval == TCL_ERROR)
1782 res = Tkinter_Error(self);
1783 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001784 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001785 LEAVE_OVERLAP_TCL
1786 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001787}
1788
1789static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001790Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001791{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001792 char *s;
1793 PyObject *res = NULL;
1794 int retval;
1795 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001796
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001797 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1798 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001799
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001800 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001801 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001802
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001803 ENTER_TCL
1804 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1805 ENTER_OVERLAP
1806 if (retval == TCL_ERROR)
1807 res = Tkinter_Error(self);
1808 else
1809 res = Py_BuildValue("l", v);
1810 LEAVE_OVERLAP_TCL
1811 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001812}
1813
1814static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001815Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001816{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001817 char *s;
1818 PyObject *res = NULL;
1819 double v;
1820 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001821
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001822 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1823 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001824 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001825 CHECK_TCL_APPARTMENT;
1826 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1827 ENTER_TCL
1828 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1829 ENTER_OVERLAP
1830 PyFPE_END_PROTECT(retval)
1831 if (retval == TCL_ERROR)
1832 res = Tkinter_Error(self);
1833 else
1834 res = Py_BuildValue("d", v);
1835 LEAVE_OVERLAP_TCL
1836 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001837}
1838
1839static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001840Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001841{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001842 char *s;
1843 PyObject *res = NULL;
1844 int retval;
1845 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001846
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001847 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1848 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001849 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001850 CHECK_TCL_APPARTMENT;
1851 ENTER_TCL
1852 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1853 ENTER_OVERLAP
1854 if (retval == TCL_ERROR)
1855 res = Tkinter_Error(self);
1856 else
1857 res = Py_BuildValue("i", v);
1858 LEAVE_OVERLAP_TCL
1859 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001860}
1861
Barry Warsawfa701a81997-01-16 00:15:11 +00001862
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001863
Guido van Rossum18468821994-06-20 07:49:28 +00001864static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001865Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001866{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001867 char *list;
1868 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03001869 const char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001870 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001871 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001872
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001873 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1874 return NULL;
1875 if (PyTclObject_Check(arg)) {
1876 int objc;
1877 Tcl_Obj **objv;
1878 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1879 ((PyTclObject*)arg)->value,
1880 &objc, &objv) == TCL_ERROR) {
1881 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001882 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001883 if (!(v = PyTuple_New(objc)))
1884 return NULL;
1885 for (i = 0; i < objc; i++) {
1886 PyObject *s = FromObj(self, objv[i]);
1887 if (!s || PyTuple_SetItem(v, i, s)) {
1888 Py_DECREF(v);
1889 return NULL;
1890 }
1891 }
1892 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001893 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001894 if (PyTuple_Check(arg)) {
1895 Py_INCREF(arg);
1896 return arg;
1897 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001898 if (PyList_Check(arg)) {
1899 return PySequence_Tuple(arg);
1900 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001901
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001902 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1903 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001904
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001905 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001906 if (Tcl_SplitList(Tkapp_Interp(self), list,
1907 &argc, &argv) == TCL_ERROR) {
1908 PyMem_Free(list);
1909 return Tkinter_Error(self);
1910 }
Guido van Rossum18468821994-06-20 07:49:28 +00001911
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001912 if (!(v = PyTuple_New(argc)))
1913 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001914
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001915 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001916 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001917 if (!s || PyTuple_SetItem(v, i, s)) {
1918 Py_DECREF(v);
1919 v = NULL;
1920 goto finally;
1921 }
1922 }
Guido van Rossum18468821994-06-20 07:49:28 +00001923
Barry Warsawfa701a81997-01-16 00:15:11 +00001924 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001925 ckfree(FREECAST argv);
1926 PyMem_Free(list);
1927 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001928}
1929
1930static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001931Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001932{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001933 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001934 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001935
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001936 if (!PyArg_ParseTuple(args, "O:split", &arg))
1937 return NULL;
1938 if (PyTclObject_Check(arg)) {
1939 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1940 int objc;
1941 Tcl_Obj **objv;
1942 int i;
1943 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1944 &objc, &objv) == TCL_ERROR) {
1945 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001946 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001947 if (objc == 0)
1948 return PyUnicode_FromString("");
1949 if (objc == 1)
1950 return FromObj(self, objv[0]);
1951 if (!(v = PyTuple_New(objc)))
1952 return NULL;
1953 for (i = 0; i < objc; i++) {
1954 PyObject *s = FromObj(self, objv[i]);
1955 if (!s || PyTuple_SetItem(v, i, s)) {
1956 Py_DECREF(v);
1957 return NULL;
1958 }
1959 }
1960 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001961 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001962 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001963 return SplitObj(arg);
1964
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001965 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1966 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001967 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001968 v = Split(list);
1969 PyMem_Free(list);
1970 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001971}
1972
Barry Warsawfa701a81997-01-16 00:15:11 +00001973
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001974
Guido van Rossum18468821994-06-20 07:49:28 +00001975/** Tcl Command **/
1976
Guido van Rossum00d93061998-05-28 23:06:38 +00001977/* Client data struct */
1978typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001979 PyObject *self;
1980 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001981} PythonCmd_ClientData;
1982
1983static int
Fred Drake509d79a2000-07-08 04:04:38 +00001984PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001985{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001986 errorInCmd = 1;
1987 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1988 LEAVE_PYTHON
1989 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001990}
1991
Guido van Rossum18468821994-06-20 07:49:28 +00001992/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001993 * function or method.
1994 */
Guido van Rossum18468821994-06-20 07:49:28 +00001995static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03001996PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001997{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001998 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001999 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002000 int i, rv;
2001 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002002
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002003 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002004
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002005 /* TBD: no error checking here since we know, via the
2006 * Tkapp_CreateCommand() that the client data is a two-tuple
2007 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002008 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002010 /* Create argument list (argv1, ..., argvN) */
2011 if (!(arg = PyTuple_New(argc - 1)))
2012 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002013
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002014 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002015 PyObject *s = unicodeFromTclString(argv[i + 1]);
2016 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002017 Py_DECREF(arg);
2018 return PythonCmd_Error(interp);
2019 }
2020 }
2021 res = PyEval_CallObject(func, arg);
2022 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002023
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002024 if (res == NULL)
2025 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002026
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002027 obj_res = AsObj(res);
2028 if (obj_res == NULL) {
2029 Py_DECREF(res);
2030 return PythonCmd_Error(interp);
2031 }
2032 else {
2033 Tcl_SetObjResult(interp, obj_res);
2034 rv = TCL_OK;
2035 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002036
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002037 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002038
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002039 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002040
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002041 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002042}
2043
2044static void
Fred Drake509d79a2000-07-08 04:04:38 +00002045PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002046{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002047 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002048
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002049 ENTER_PYTHON
2050 Py_XDECREF(data->self);
2051 Py_XDECREF(data->func);
2052 PyMem_DEL(data);
2053 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002054}
2055
Barry Warsawfa701a81997-01-16 00:15:11 +00002056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002057
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002058
Benjamin Peterson5879d412009-03-30 14:51:56 +00002059#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002060TCL_DECLARE_MUTEX(command_mutex)
2061
2062typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063 Tcl_Event ev;
2064 Tcl_Interp* interp;
2065 char *name;
2066 int create;
2067 int *status;
2068 ClientData *data;
2069 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002070} CommandEvent;
2071
2072static int
2073Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002074{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002075 if (ev->create)
2076 *ev->status = Tcl_CreateCommand(
2077 ev->interp, ev->name, PythonCmd,
2078 ev->data, PythonCmdDelete) == NULL;
2079 else
2080 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2081 Tcl_MutexLock(&command_mutex);
2082 Tcl_ConditionNotify(ev->done);
2083 Tcl_MutexUnlock(&command_mutex);
2084 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002085}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002086#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002087
2088static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002089Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002090{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002091 TkappObject *self = (TkappObject*)selfptr;
2092 PythonCmd_ClientData *data;
2093 char *cmdName;
2094 PyObject *func;
2095 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002096
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002097 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2098 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002099 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002100 if (!PyCallable_Check(func)) {
2101 PyErr_SetString(PyExc_TypeError, "command not callable");
2102 return NULL;
2103 }
Guido van Rossum18468821994-06-20 07:49:28 +00002104
Martin v. Löwisa9656492003-03-30 08:44:58 +00002105#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002106 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2107 !WaitForMainloop(self))
2108 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002109#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002110
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002111 data = PyMem_NEW(PythonCmd_ClientData, 1);
2112 if (!data)
2113 return PyErr_NoMemory();
2114 Py_INCREF(self);
2115 Py_INCREF(func);
2116 data->self = selfptr;
2117 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002118#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002119 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2120 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002121 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2122 if (ev == NULL) {
2123 PyErr_NoMemory();
2124 PyMem_DEL(data);
2125 return NULL;
2126 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002127 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2128 ev->interp = self->interp;
2129 ev->create = 1;
2130 ev->name = cmdName;
2131 ev->data = (ClientData)data;
2132 ev->status = &err;
2133 ev->done = &cond;
2134 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2135 Tcl_ConditionFinalize(&cond);
2136 }
2137 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002138#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002139 {
2140 ENTER_TCL
2141 err = Tcl_CreateCommand(
2142 Tkapp_Interp(self), cmdName, PythonCmd,
2143 (ClientData)data, PythonCmdDelete) == NULL;
2144 LEAVE_TCL
2145 }
2146 if (err) {
2147 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2148 PyMem_DEL(data);
2149 return NULL;
2150 }
Guido van Rossum18468821994-06-20 07:49:28 +00002151
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002152 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002153}
2154
Barry Warsawfa701a81997-01-16 00:15:11 +00002155
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002156
Guido van Rossum18468821994-06-20 07:49:28 +00002157static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002158Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002159{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 TkappObject *self = (TkappObject*)selfptr;
2161 char *cmdName;
2162 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002163
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002164 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2165 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002166 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002167
2168#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002169 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2170 Tcl_Condition cond = NULL;
2171 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002172 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2173 if (ev == NULL) {
2174 PyErr_NoMemory();
2175 return NULL;
2176 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002177 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2178 ev->interp = self->interp;
2179 ev->create = 0;
2180 ev->name = cmdName;
2181 ev->status = &err;
2182 ev->done = &cond;
2183 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2184 &command_mutex);
2185 Tcl_ConditionFinalize(&cond);
2186 }
2187 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002188#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002189 {
2190 ENTER_TCL
2191 err = Tcl_DeleteCommand(self->interp, cmdName);
2192 LEAVE_TCL
2193 }
2194 if (err == -1) {
2195 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2196 return NULL;
2197 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002198 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002199}
2200
Barry Warsawfa701a81997-01-16 00:15:11 +00002201
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002202
Guido van Rossum00d93061998-05-28 23:06:38 +00002203#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002204/** File Handler **/
2205
Guido van Rossum00d93061998-05-28 23:06:38 +00002206typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002207 PyObject *func;
2208 PyObject *file;
2209 int id;
2210 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002211} FileHandler_ClientData;
2212
2213static FileHandler_ClientData *HeadFHCD;
2214
2215static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002216NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002217{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002218 FileHandler_ClientData *p;
2219 p = PyMem_NEW(FileHandler_ClientData, 1);
2220 if (p != NULL) {
2221 Py_XINCREF(func);
2222 Py_XINCREF(file);
2223 p->func = func;
2224 p->file = file;
2225 p->id = id;
2226 p->next = HeadFHCD;
2227 HeadFHCD = p;
2228 }
2229 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002230}
2231
2232static void
Fred Drake509d79a2000-07-08 04:04:38 +00002233DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002234{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002235 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002236
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002237 pp = &HeadFHCD;
2238 while ((p = *pp) != NULL) {
2239 if (p->id == id) {
2240 *pp = p->next;
2241 Py_XDECREF(p->func);
2242 Py_XDECREF(p->file);
2243 PyMem_DEL(p);
2244 }
2245 else
2246 pp = &p->next;
2247 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002248}
2249
Guido van Rossuma597dde1995-01-10 20:56:29 +00002250static void
Fred Drake509d79a2000-07-08 04:04:38 +00002251FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002252{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002253 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2254 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002255
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002256 ENTER_PYTHON
2257 func = data->func;
2258 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002260 arg = Py_BuildValue("(Oi)", file, (long) mask);
2261 res = PyEval_CallObject(func, arg);
2262 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002263
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002264 if (res == NULL) {
2265 errorInCmd = 1;
2266 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2267 }
2268 Py_XDECREF(res);
2269 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002270}
2271
Guido van Rossum18468821994-06-20 07:49:28 +00002272static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002273Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2274 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002275{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002276 FileHandler_ClientData *data;
2277 PyObject *file, *func;
2278 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002280 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2281 &file, &mask, &func))
2282 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002284 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002285
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002286 tfile = PyObject_AsFileDescriptor(file);
2287 if (tfile < 0)
2288 return NULL;
2289 if (!PyCallable_Check(func)) {
2290 PyErr_SetString(PyExc_TypeError, "bad argument list");
2291 return NULL;
2292 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002293
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002294 data = NewFHCD(func, file, tfile);
2295 if (data == NULL)
2296 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002298 /* Ought to check for null Tcl_File object... */
2299 ENTER_TCL
2300 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2301 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002302 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002303}
2304
2305static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002306Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002307{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002308 PyObject *file;
2309 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002310
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002311 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2312 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002314 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002316 tfile = PyObject_AsFileDescriptor(file);
2317 if (tfile < 0)
2318 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002319
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002320 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002321
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002322 /* Ought to check for null Tcl_File object... */
2323 ENTER_TCL
2324 Tcl_DeleteFileHandler(tfile);
2325 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002326 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002327}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002328#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002330
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002331/**** Tktt Object (timer token) ****/
2332
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002333static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002334
Guido van Rossum00d93061998-05-28 23:06:38 +00002335typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002336 PyObject_HEAD
2337 Tcl_TimerToken token;
2338 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002339} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002340
2341static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002342Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002343{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002344 TkttObject *v = (TkttObject *)self;
2345 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002346
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002347 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2348 return NULL;
2349 if (v->token != NULL) {
2350 Tcl_DeleteTimerHandler(v->token);
2351 v->token = NULL;
2352 }
2353 if (func != NULL) {
2354 v->func = NULL;
2355 Py_DECREF(func);
2356 Py_DECREF(v); /* See Tktt_New() */
2357 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002358 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002359}
2360
2361static PyMethodDef Tktt_methods[] =
2362{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002363 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2364 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002365};
2366
2367static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002368Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002369{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002370 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002371
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002372 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002373 if (v == NULL)
2374 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002375 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002377 Py_INCREF(func);
2378 v->token = NULL;
2379 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002380
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002381 /* Extra reference, deleted when called or when handler is deleted */
2382 Py_INCREF(v);
2383 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002384}
2385
2386static void
Fred Drake509d79a2000-07-08 04:04:38 +00002387Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002388{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002389 TkttObject *v = (TkttObject *)self;
2390 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002391 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002393 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002395 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002396 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002397}
2398
Guido van Rossum597ac201998-05-12 14:36:19 +00002399static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002400Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002401{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002402 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002403 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2404 v,
2405 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002406}
2407
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002408static PyType_Slot Tktt_Type_slots[] = {
2409 {Py_tp_dealloc, Tktt_Dealloc},
2410 {Py_tp_repr, Tktt_Repr},
2411 {Py_tp_methods, Tktt_methods},
2412 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002413};
2414
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002415static PyType_Spec Tktt_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002416 "_tkinter.tktimertoken",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002417 sizeof(TkttObject),
2418 0,
2419 Py_TPFLAGS_DEFAULT,
2420 Tktt_Type_slots,
2421};
Barry Warsawfa701a81997-01-16 00:15:11 +00002422
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002423
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002424/** Timer Handler **/
2425
2426static void
Fred Drake509d79a2000-07-08 04:04:38 +00002427TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002428{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002429 TkttObject *v = (TkttObject *)clientData;
2430 PyObject *func = v->func;
2431 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002432
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002433 if (func == NULL)
2434 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002435
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002436 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002438 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002439
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002440 res = PyEval_CallObject(func, NULL);
2441 Py_DECREF(func);
2442 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002443
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002444 if (res == NULL) {
2445 errorInCmd = 1;
2446 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2447 }
2448 else
2449 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002450
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002451 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002452}
2453
2454static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002455Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002456{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002457 int milliseconds;
2458 PyObject *func;
2459 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002461 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2462 &milliseconds, &func))
2463 return NULL;
2464 if (!PyCallable_Check(func)) {
2465 PyErr_SetString(PyExc_TypeError, "bad argument list");
2466 return NULL;
2467 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002469 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 v = Tktt_New(func);
2472 if (v) {
2473 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2474 (ClientData)v);
2475 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002478}
2479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002480
Guido van Rossum18468821994-06-20 07:49:28 +00002481/** Event Loop **/
2482
Guido van Rossum18468821994-06-20 07:49:28 +00002483static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002484Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002485{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002486 int threshold = 0;
2487 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002488#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002489 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002490#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002491
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002492 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2493 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002494
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002495 CHECK_TCL_APPARTMENT;
2496 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002497
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002498 quitMainLoop = 0;
2499 while (Tk_GetNumMainWindows() > threshold &&
2500 !quitMainLoop &&
2501 !errorInCmd)
2502 {
2503 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002504
2505#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002506 if (self->threaded) {
2507 /* Allow other Python threads to run. */
2508 ENTER_TCL
2509 result = Tcl_DoOneEvent(0);
2510 LEAVE_TCL
2511 }
2512 else {
2513 Py_BEGIN_ALLOW_THREADS
2514 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2515 tcl_tstate = tstate;
2516 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2517 tcl_tstate = NULL;
2518 if(tcl_lock)PyThread_release_lock(tcl_lock);
2519 if (result == 0)
2520 Sleep(Tkinter_busywaitinterval);
2521 Py_END_ALLOW_THREADS
2522 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002523#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002524 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002525#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002526
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002527 if (PyErr_CheckSignals() != 0) {
2528 self->dispatching = 0;
2529 return NULL;
2530 }
2531 if (result < 0)
2532 break;
2533 }
2534 self->dispatching = 0;
2535 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002537 if (errorInCmd) {
2538 errorInCmd = 0;
2539 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2540 excInCmd = valInCmd = trbInCmd = NULL;
2541 return NULL;
2542 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002543 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002544}
2545
2546static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002547Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002548{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002549 int flags = 0;
2550 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002551
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002552 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2553 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002554
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002555 ENTER_TCL
2556 rv = Tcl_DoOneEvent(flags);
2557 LEAVE_TCL
2558 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002559}
2560
2561static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002562Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002563{
2564
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002565 if (!PyArg_ParseTuple(args, ":quit"))
2566 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002567
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002568 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002569 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002570}
2571
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002572static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002573Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002574{
2575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002576 if (!PyArg_ParseTuple(args, ":interpaddr"))
2577 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002578
Victor Stinnere1040e22013-09-05 00:22:24 +02002579 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002580}
2581
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002582static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002583Tkapp_TkInit(PyObject *self, PyObject *args)
2584{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002585 Tcl_Interp *interp = Tkapp_Interp(self);
2586 const char * _tk_exists = NULL;
2587 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002588
Guilherme Polob681df42009-02-09 22:33:59 +00002589#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002590 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2591 * first call failed.
2592 * To avoid the deadlock, we just refuse the second call through
2593 * a static variable.
2594 */
2595 if (tk_load_failed) {
2596 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2597 return NULL;
2598 }
Guilherme Polob681df42009-02-09 22:33:59 +00002599#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002601 /* We want to guard against calling Tk_Init() multiple times */
2602 CHECK_TCL_APPARTMENT;
2603 ENTER_TCL
2604 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2605 ENTER_OVERLAP
2606 if (err == TCL_ERROR) {
2607 /* This sets an exception, but we cannot return right
2608 away because we need to exit the overlap first. */
2609 Tkinter_Error(self);
2610 } else {
2611 _tk_exists = Tkapp_Result(self);
2612 }
2613 LEAVE_OVERLAP_TCL
2614 if (err == TCL_ERROR) {
2615 return NULL;
2616 }
2617 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2618 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002619 PyErr_SetString(Tkinter_TclError,
2620 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002621#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002622 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002623#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002624 return NULL;
2625 }
2626 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002627 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002628}
Barry Warsawfa701a81997-01-16 00:15:11 +00002629
Martin v. Löwisffad6332002-11-26 09:28:05 +00002630static PyObject *
2631Tkapp_WantObjects(PyObject *self, PyObject *args)
2632{
2633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002634 int wantobjects = -1;
2635 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2636 return NULL;
2637 if (wantobjects == -1)
2638 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2639 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002640
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002641 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002642}
2643
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002644static PyObject *
2645Tkapp_WillDispatch(PyObject *self, PyObject *args)
2646{
2647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002648 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002649
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002650 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002651}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002652
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002653
Guido van Rossum18468821994-06-20 07:49:28 +00002654/**** Tkapp Method List ****/
2655
2656static PyMethodDef Tkapp_methods[] =
2657{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002658 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2659 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2660 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002661 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002662 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2663 {"record", Tkapp_Record, METH_VARARGS},
2664 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2665 {"setvar", Tkapp_SetVar, METH_VARARGS},
2666 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2667 {"getvar", Tkapp_GetVar, METH_VARARGS},
2668 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2669 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2670 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2671 {"getint", Tkapp_GetInt, METH_VARARGS},
2672 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2673 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2674 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2675 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2676 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2677 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2678 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2679 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002680 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2681 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002682#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002683 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2684 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002685#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002686 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2687 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2688 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2689 {"quit", Tkapp_Quit, METH_VARARGS},
2690 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2691 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2692 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002693};
2694
Barry Warsawfa701a81997-01-16 00:15:11 +00002695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002696
Guido van Rossum18468821994-06-20 07:49:28 +00002697/**** Tkapp Type Methods ****/
2698
2699static void
Fred Drake509d79a2000-07-08 04:04:38 +00002700Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002701{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002702 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002703 /*CHECK_TCL_APPARTMENT;*/
2704 ENTER_TCL
2705 Tcl_DeleteInterp(Tkapp_Interp(self));
2706 LEAVE_TCL
2707 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002708 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002709 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002710}
2711
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002712static PyType_Slot Tkapp_Type_slots[] = {
2713 {Py_tp_dealloc, Tkapp_Dealloc},
2714 {Py_tp_methods, Tkapp_methods},
2715 {0, 0}
2716};
2717
2718
2719static PyType_Spec Tkapp_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002720 "_tkinter.tkapp",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002721 sizeof(TkappObject),
2722 0,
2723 Py_TPFLAGS_DEFAULT,
2724 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002725};
2726
Barry Warsawfa701a81997-01-16 00:15:11 +00002727
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002728
Guido van Rossum18468821994-06-20 07:49:28 +00002729/**** Tkinter Module ****/
2730
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002731typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002732 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002733 Py_ssize_t size; /* current size */
2734 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002735} FlattenContext;
2736
2737static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002738_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002739{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002740 /* expand tuple to hold (at least) size new items.
2741 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002742
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002743 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002744
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002745 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002746 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002747
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002748 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002749
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002750 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002751}
2752
2753static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002754_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002755{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002756 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002757
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002758 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002759
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002760 if (depth > 1000) {
2761 PyErr_SetString(PyExc_ValueError,
2762 "nesting too deep in _flatten");
2763 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002764 } else if (PyTuple_Check(item) || PyList_Check(item)) {
2765 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002766 /* preallocate (assume no nesting) */
2767 if (context->size + size > context->maxsize &&
2768 !_bump(context, size))
2769 return 0;
2770 /* copy items to output tuple */
2771 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002772 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002773 if (PyList_Check(o) || PyTuple_Check(o)) {
2774 if (!_flatten1(context, o, depth + 1))
2775 return 0;
2776 } else if (o != Py_None) {
2777 if (context->size + 1 > context->maxsize &&
2778 !_bump(context, 1))
2779 return 0;
2780 Py_INCREF(o);
2781 PyTuple_SET_ITEM(context->tuple,
2782 context->size++, o);
2783 }
2784 }
2785 } else {
2786 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2787 return 0;
2788 }
2789 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002790}
2791
2792static PyObject *
2793Tkinter_Flatten(PyObject* self, PyObject* args)
2794{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002795 FlattenContext context;
2796 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002798 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2799 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002800
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002801 context.maxsize = PySequence_Size(item);
2802 if (context.maxsize < 0)
2803 return NULL;
2804 if (context.maxsize == 0)
2805 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002806
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002807 context.tuple = PyTuple_New(context.maxsize);
2808 if (!context.tuple)
2809 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002810
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002811 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002812
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002813 if (!_flatten1(&context, item,0))
2814 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002815
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002816 if (_PyTuple_Resize(&context.tuple, context.size))
2817 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002818
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002819 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002820}
2821
Guido van Rossum18468821994-06-20 07:49:28 +00002822static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002823Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002824{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002825 char *screenName = NULL;
2826 char *baseName = NULL; /* XXX this is not used anymore;
2827 try getting rid of it. */
2828 char *className = NULL;
2829 int interactive = 0;
Serhiy Storchaka9e7cbda2014-05-28 16:57:55 +03002830 int wantobjects = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002831 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2832 int sync = 0; /* pass -sync to wish */
2833 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002834
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002835 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002837 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2838 &screenName, &baseName, &className,
2839 &interactive, &wantobjects, &wantTk,
2840 &sync, &use))
2841 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002842 CHECK_STRING_LENGTH(screenName);
2843 CHECK_STRING_LENGTH(baseName);
2844 CHECK_STRING_LENGTH(className);
2845 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00002846
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002847 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002848 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002849 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002850}
2851
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002852static PyObject *
2853Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2854{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002855 int new_val;
2856 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2857 return NULL;
2858 if (new_val < 0) {
2859 PyErr_SetString(PyExc_ValueError,
2860 "busywaitinterval must be >= 0");
2861 return NULL;
2862 }
2863 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002864 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002865}
2866
2867static char setbusywaitinterval_doc[] =
2868"setbusywaitinterval(n) -> None\n\
2869\n\
2870Set the busy-wait interval in milliseconds between successive\n\
2871calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2872It should be set to a divisor of the maximum time between\n\
2873frames in an animation.";
2874
2875static PyObject *
2876Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2877{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002878 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002879}
2880
2881static char getbusywaitinterval_doc[] =
2882"getbusywaitinterval() -> int\n\
2883\n\
2884Return the current busy-wait interval between successive\n\
2885calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2886
Guido van Rossum18468821994-06-20 07:49:28 +00002887static PyMethodDef moduleMethods[] =
2888{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002889 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2890 {"create", Tkinter_Create, METH_VARARGS},
2891 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2892 setbusywaitinterval_doc},
2893 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2894 METH_NOARGS, getbusywaitinterval_doc},
2895 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002896};
2897
Guido van Rossum7bf15641998-05-22 18:28:17 +00002898#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002899
2900static int stdin_ready = 0;
2901
Guido van Rossumad4db171998-06-13 13:56:28 +00002902#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002903static void
Fred Drake509d79a2000-07-08 04:04:38 +00002904MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002905{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002906 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002907}
Guido van Rossumad4db171998-06-13 13:56:28 +00002908#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002909
Martin v. Löwisa9656492003-03-30 08:44:58 +00002910#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002911static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002912#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002913
Guido van Rossum18468821994-06-20 07:49:28 +00002914static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002915EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002916{
Guido van Rossumad4db171998-06-13 13:56:28 +00002917#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002918 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002919#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002920#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002921 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002922#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002923 stdin_ready = 0;
2924 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002925#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002926 tfile = fileno(stdin);
2927 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002928#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002929 while (!errorInCmd && !stdin_ready) {
2930 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002931#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002932 if (_kbhit()) {
2933 stdin_ready = 1;
2934 break;
2935 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002936#endif
2937#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002938 Py_BEGIN_ALLOW_THREADS
2939 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2940 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002941
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002942 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002943
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002944 tcl_tstate = NULL;
2945 if(tcl_lock)PyThread_release_lock(tcl_lock);
2946 if (result == 0)
2947 Sleep(Tkinter_busywaitinterval);
2948 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002949#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002950 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002951#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002952
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002953 if (result < 0)
2954 break;
2955 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002956#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002957 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002958#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002959 if (errorInCmd) {
2960 errorInCmd = 0;
2961 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2962 excInCmd = valInCmd = trbInCmd = NULL;
2963 PyErr_Print();
2964 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002965#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002966 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002967#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002968 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002969}
Guido van Rossum18468821994-06-20 07:49:28 +00002970
Guido van Rossum00d93061998-05-28 23:06:38 +00002971#endif
2972
Guido van Rossum7bf15641998-05-22 18:28:17 +00002973static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002974EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002975{
Guido van Rossum00d93061998-05-28 23:06:38 +00002976#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002977 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002978#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002979 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002980#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002981 PyOS_InputHook = EventHook;
2982 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002983#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002984}
2985
2986static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002987DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002988{
Guido van Rossum00d93061998-05-28 23:06:38 +00002989#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002990 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2991 PyOS_InputHook = NULL;
2992 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002993#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002994}
2995
Barry Warsawfa701a81997-01-16 00:15:11 +00002996
Martin v. Löwis1a214512008-06-11 05:26:20 +00002997static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002998 PyModuleDef_HEAD_INIT,
2999 "_tkinter",
3000 NULL,
3001 -1,
3002 moduleMethods,
3003 NULL,
3004 NULL,
3005 NULL,
3006 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003007};
3008
Mark Hammond62b1ab12002-07-23 06:31:15 +00003009PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003010PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003011{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003012 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003013
Guido van Rossum00d93061998-05-28 23:06:38 +00003014#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003015 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003016 if (tcl_lock == NULL)
3017 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003018#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003019
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003020 m = PyModule_Create(&_tkintermodule);
3021 if (m == NULL)
3022 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003023
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003024 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3025 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003026 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003027 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003028 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003029 Py_INCREF(o);
3030 if (PyModule_AddObject(m, "TclError", o)) {
3031 Py_DECREF(o);
3032 Py_DECREF(m);
3033 return NULL;
3034 }
3035 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003036
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003037 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3038 Py_DECREF(m);
3039 return NULL;
3040 }
3041 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3042 Py_DECREF(m);
3043 return NULL;
3044 }
3045 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3046 Py_DECREF(m);
3047 return NULL;
3048 }
3049 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3050 Py_DECREF(m);
3051 return NULL;
3052 }
3053 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3054 Py_DECREF(m);
3055 return NULL;
3056 }
3057 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3058 Py_DECREF(m);
3059 return NULL;
3060 }
3061 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3062 Py_DECREF(m);
3063 return NULL;
3064 }
3065 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3066 Py_DECREF(m);
3067 return NULL;
3068 }
3069 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3070 Py_DECREF(m);
3071 return NULL;
3072 }
3073 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3074 Py_DECREF(m);
3075 return NULL;
3076 }
3077 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3078 Py_DECREF(m);
3079 return NULL;
3080 }
3081
3082 o = PyType_FromSpec(&Tkapp_Type_spec);
3083 if (o == NULL) {
3084 Py_DECREF(m);
3085 return NULL;
3086 }
3087 if (PyModule_AddObject(m, "TkappType", o)) {
3088 Py_DECREF(o);
3089 Py_DECREF(m);
3090 return NULL;
3091 }
3092 Tkapp_Type = o;
3093
3094 o = PyType_FromSpec(&Tktt_Type_spec);
3095 if (o == NULL) {
3096 Py_DECREF(m);
3097 return NULL;
3098 }
3099 if (PyModule_AddObject(m, "TkttType", o)) {
3100 Py_DECREF(o);
3101 Py_DECREF(m);
3102 return NULL;
3103 }
3104 Tktt_Type = o;
3105
3106 o = PyType_FromSpec(&PyTclObject_Type_spec);
3107 if (o == NULL) {
3108 Py_DECREF(m);
3109 return NULL;
3110 }
3111 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3112 Py_DECREF(o);
3113 Py_DECREF(m);
3114 return NULL;
3115 }
3116 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003117
3118#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003119 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3120 * start waking up. Note that Tcl_FindExecutable will do this, this
3121 * code must be above it! The original warning from
3122 * tkMacOSXAppInit.c is copied below.
3123 *
3124 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3125 * Tcl interpreter for now. It probably should work to do this
3126 * in the other order, but for now it doesn't seem to.
3127 *
3128 */
3129 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003130#endif
3131
3132
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003133 /* This helps the dynamic loader; in Unicode aware Tcl versions
3134 it also helps Tcl find its encodings. */
3135 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3136 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003137 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003138 if (cexe)
3139 Tcl_FindExecutable(PyBytes_AsString(cexe));
3140 Py_XDECREF(cexe);
3141 Py_DECREF(uexe);
3142 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003143
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003144 if (PyErr_Occurred()) {
3145 Py_DECREF(m);
3146 return NULL;
3147 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003148
Guido van Rossum43ff8681998-07-14 18:02:13 +00003149#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003150 /* This was not a good idea; through <Destroy> bindings,
3151 Tcl_Finalize() may invoke Python code but at that point the
3152 interpreter and thread state have already been destroyed! */
3153 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003154#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003155 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003156}