blob: 52069ec8b9e72d05481e1ecda2f712d286f7641c [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. */
Zachary Ware037605b2014-08-05 11:54:34 -0500232 const Tcl_ObjType *BooleanType;
233 const Tcl_ObjType *ByteArrayType;
234 const Tcl_ObjType *DoubleType;
235 const Tcl_ObjType *IntType;
236 const Tcl_ObjType *ListType;
237 const Tcl_ObjType *ProcBodyType;
238 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000239} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000240
Guido van Rossum18468821994-06-20 07:49:28 +0000241#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000242#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000243
Guido van Rossum35d43371997-08-02 00:09:09 +0000244#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000245(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000246
Barry Warsawfa701a81997-01-16 00:15:11 +0000247
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000248
Guido van Rossum18468821994-06-20 07:49:28 +0000249/**** Error Handling ****/
250
251static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000252static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000253static int errorInCmd = 0;
254static PyObject *excInCmd;
255static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000256static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000257
Guilherme Polob681df42009-02-09 22:33:59 +0000258#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000259static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000260#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000262
Guido van Rossum18468821994-06-20 07:49:28 +0000263static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000264Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000265{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000266 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
267 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000268}
269
Barry Warsawfa701a81997-01-16 00:15:11 +0000270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000271
Guido van Rossum18468821994-06-20 07:49:28 +0000272/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000273
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000274static int Tkinter_busywaitinterval = 20;
275
Guido van Rossum00d93061998-05-28 23:06:38 +0000276#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000277#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000278
Guido van Rossum00d93061998-05-28 23:06:38 +0000279/* Millisecond sleep() for Unix platforms. */
280
281static void
Fred Drake509d79a2000-07-08 04:04:38 +0000282Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000283{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000284 /* XXX Too bad if you don't have select(). */
285 struct timeval t;
286 t.tv_sec = milli/1000;
287 t.tv_usec = (milli%1000) * 1000;
288 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000289}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000290#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000291
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000292/* Wait up to 1s for the mainloop to come up. */
293
294static int
295WaitForMainloop(TkappObject* self)
296{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000297 int i;
298 for (i = 0; i < 10; i++) {
299 if (self->dispatching)
300 return 1;
301 Py_BEGIN_ALLOW_THREADS
302 Sleep(100);
303 Py_END_ALLOW_THREADS
304 }
305 if (self->dispatching)
306 return 1;
307 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
308 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000309}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000310#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000313
Guido van Rossum18468821994-06-20 07:49:28 +0000314#define ARGSZ 64
315
Barry Warsawfa701a81997-01-16 00:15:11 +0000316
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000317
Guido van Rossum18468821994-06-20 07:49:28 +0000318static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200319unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
320{
321 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
322 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
323 /* Tcl encodes null character as \xc0\x80 */
324 if (memchr(s, '\xc0', size)) {
325 char *buf, *q;
326 const char *e = s + size;
327 PyErr_Clear();
328 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300329 if (buf == NULL) {
330 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200331 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300332 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200333 while (s != e) {
334 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
335 *q++ = '\0';
336 s += 2;
337 }
338 else
339 *q++ = *s++;
340 }
341 s = buf;
342 size = q - s;
343 r = PyUnicode_DecodeUTF8(s, size, NULL);
344 PyMem_Free(buf);
345 }
346 }
347 return r;
348}
349
350static PyObject *
351unicodeFromTclString(const char *s)
352{
353 return unicodeFromTclStringAndSize(s, strlen(s));
354}
355
356static PyObject *
357unicodeFromTclObj(Tcl_Obj *value)
358{
359 int len;
360 char *s = Tcl_GetStringFromObj(value, &len);
361 return unicodeFromTclStringAndSize(s, len);
362}
363
364
365static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300366Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000367{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000368 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300369 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000370 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000372 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300373 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000374 }
Guido van Rossum18468821994-06-20 07:49:28 +0000375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000376 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
377 /* Not a list.
378 * Could be a quoted string containing funnies, e.g. {"}.
379 * Return the string itself.
380 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200381 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000382 }
Guido van Rossum18468821994-06-20 07:49:28 +0000383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000384 if (argc == 0)
385 v = PyUnicode_FromString("");
386 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200387 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000388 else if ((v = PyTuple_New(argc)) != NULL) {
389 int i;
390 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000392 for (i = 0; i < argc; i++) {
393 if ((w = Split(argv[i])) == NULL) {
394 Py_DECREF(v);
395 v = NULL;
396 break;
397 }
398 PyTuple_SetItem(v, i, w);
399 }
400 }
401 Tcl_Free(FREECAST argv);
402 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000403}
404
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300405/* In some cases, Tcl will still return strings that are supposed to
406 be lists. SplitObj walks through a nested tuple, finding string
407 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000408
Martin v. Löwis59683e82008-06-13 07:50:45 +0000409static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000410SplitObj(PyObject *arg)
411{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000412 if (PyTuple_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200413 Py_ssize_t i, size;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000414 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000415
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000416 size = PyTuple_Size(arg);
417 result = NULL;
418 /* Recursively invoke SplitObj for all tuple items.
419 If this does not return a new object, no action is
420 needed. */
421 for(i = 0; i < size; i++) {
422 elem = PyTuple_GetItem(arg, i);
423 newelem = SplitObj(elem);
424 if (!newelem) {
425 Py_XDECREF(result);
426 return NULL;
427 }
428 if (!result) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200429 Py_ssize_t k;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000430 if (newelem == elem) {
431 Py_DECREF(newelem);
432 continue;
433 }
434 result = PyTuple_New(size);
435 if (!result)
436 return NULL;
437 for(k = 0; k < i; k++) {
438 elem = PyTuple_GetItem(arg, k);
439 Py_INCREF(elem);
440 PyTuple_SetItem(result, k, elem);
441 }
442 }
443 PyTuple_SetItem(result, i, newelem);
444 }
445 if (result)
446 return result;
447 /* Fall through, returning arg. */
448 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300449 else if (PyList_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200450 Py_ssize_t i, size;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300451 PyObject *elem, *newelem, *result;
452
453 size = PyList_GET_SIZE(arg);
454 result = PyTuple_New(size);
455 if (!result)
456 return NULL;
457 /* Recursively invoke SplitObj for all list items. */
458 for(i = 0; i < size; i++) {
459 elem = PyList_GET_ITEM(arg, i);
460 newelem = SplitObj(elem);
461 if (!newelem) {
462 Py_XDECREF(result);
463 return NULL;
464 }
465 PyTuple_SetItem(result, i, newelem);
466 }
467 return result;
468 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300469 else if (PyUnicode_Check(arg)) {
470 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300471 const char **argv;
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300472 char *list = PyUnicode_AsUTF8(arg);
473
474 if (list == NULL ||
475 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
476 Py_INCREF(arg);
477 return arg;
478 }
479 Tcl_Free(FREECAST argv);
480 if (argc > 1)
481 return Split(list);
482 /* Fall through, returning arg. */
483 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000484 else if (PyBytes_Check(arg)) {
485 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300486 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000487 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000488
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000489 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
490 Py_INCREF(arg);
491 return arg;
492 }
493 Tcl_Free(FREECAST argv);
494 if (argc > 1)
495 return Split(PyBytes_AsString(arg));
496 /* Fall through, returning arg. */
497 }
498 Py_INCREF(arg);
499 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000500}
Barry Warsawfa701a81997-01-16 00:15:11 +0000501
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000502
Guido van Rossum18468821994-06-20 07:49:28 +0000503/**** Tkapp Object ****/
504
505#ifndef WITH_APPINIT
506int
Fred Drake509d79a2000-07-08 04:04:38 +0000507Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000508{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000509 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000510
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000511 if (Tcl_Init(interp) == TCL_ERROR) {
512 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
513 return TCL_ERROR;
514 }
Guilherme Polob681df42009-02-09 22:33:59 +0000515
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000516 _tkinter_skip_tk_init = Tcl_GetVar(interp,
517 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
518 if (_tkinter_skip_tk_init != NULL &&
519 strcmp(_tkinter_skip_tk_init, "1") == 0) {
520 return TCL_OK;
521 }
Guilherme Polob681df42009-02-09 22:33:59 +0000522
523#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 if (tk_load_failed) {
525 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
526 return TCL_ERROR;
527 }
Guilherme Polob681df42009-02-09 22:33:59 +0000528#endif
529
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000530 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000531#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000532 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000533#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000534 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
535 return TCL_ERROR;
536 }
Guilherme Polob681df42009-02-09 22:33:59 +0000537
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000538 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000539}
540#endif /* !WITH_APPINIT */
541
Guido van Rossum18468821994-06-20 07:49:28 +0000542
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000543
Barry Warsawfa701a81997-01-16 00:15:11 +0000544
545/* Initialize the Tk application; see the `main' function in
546 * `tkMain.c'.
547 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000548
Thomas Wouters58d05102000-07-24 14:43:35 +0000549static void EnableEventHook(void); /* Forward */
550static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000551
Barry Warsawfa701a81997-01-16 00:15:11 +0000552static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300553Tkapp_New(const char *screenName, const char *className,
554 int interactive, int wantobjects, int wantTk, int sync,
555 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000556{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 TkappObject *v;
558 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000559
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300560 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000561 if (v == NULL)
562 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200563 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000564
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000565 v->interp = Tcl_CreateInterp();
566 v->wantobjects = wantobjects;
567 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
568 TCL_GLOBAL_ONLY) != NULL;
569 v->thread_id = Tcl_GetCurrentThread();
570 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000571
572#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000573 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300574 PyErr_SetString(PyExc_RuntimeError,
575 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000576 Py_DECREF(v);
577 return 0;
578 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000579#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000580#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000581 if (v->threaded && tcl_lock) {
582 /* If Tcl is threaded, we don't need the lock. */
583 PyThread_free_lock(tcl_lock);
584 tcl_lock = NULL;
585 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000586#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000587
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000588 v->BooleanType = Tcl_GetObjType("boolean");
589 v->ByteArrayType = Tcl_GetObjType("bytearray");
590 v->DoubleType = Tcl_GetObjType("double");
591 v->IntType = Tcl_GetObjType("int");
592 v->ListType = Tcl_GetObjType("list");
593 v->ProcBodyType = Tcl_GetObjType("procbody");
594 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000595
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000596 /* Delete the 'exit' command, which can screw things up */
597 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000598
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000599 if (screenName != NULL)
600 Tcl_SetVar2(v->interp, "env", "DISPLAY",
601 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000602
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000603 if (interactive)
604 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
605 else
606 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000607
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000608 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200609 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000610 if (!argv0) {
611 PyErr_NoMemory();
612 Py_DECREF(v);
613 return NULL;
614 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000615
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200617 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
618 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000619 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200620 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000621
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000622 if (! wantTk) {
623 Tcl_SetVar(v->interp,
624 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
625 }
Guilherme Polob681df42009-02-09 22:33:59 +0000626#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000627 else if (tk_load_failed) {
628 Tcl_SetVar(v->interp,
629 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
630 }
Guilherme Polob681df42009-02-09 22:33:59 +0000631#endif
David Aschere2b4b322004-02-18 05:59:53 +0000632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 /* some initial arguments need to be in argv */
634 if (sync || use) {
635 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200636 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000637
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 if (sync)
639 len += sizeof "-sync";
640 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200641 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000642
Victor Stinneree6c3c72014-09-11 17:50:21 +0200643 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000644 if (!args) {
645 PyErr_NoMemory();
646 Py_DECREF(v);
647 return NULL;
648 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 args[0] = '\0';
651 if (sync)
652 strcat(args, "-sync");
653 if (use) {
654 if (sync)
655 strcat(args, " ");
656 strcat(args, "-use ");
657 strcat(args, use);
658 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000659
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200661 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 if (Tcl_AppInit(v->interp) != TCL_OK) {
665 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000666#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000667 if (wantTk) {
668 const char *_tkinter_tk_failed;
669 _tkinter_tk_failed = Tcl_GetVar(v->interp,
670 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000672 if ( _tkinter_tk_failed != NULL &&
673 strcmp(_tkinter_tk_failed, "1") == 0) {
674 tk_load_failed = 1;
675 }
676 }
Guilherme Polob681df42009-02-09 22:33:59 +0000677#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000678 Py_DECREF((PyObject *)v);
679 return (TkappObject *)result;
680 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000685}
686
Barry Warsawfa701a81997-01-16 00:15:11 +0000687
Benjamin Peterson5879d412009-03-30 14:51:56 +0000688#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000689static void
690Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000692{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000693 Py_BEGIN_ALLOW_THREADS;
694 Tcl_MutexLock(mutex);
695 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
696 Tcl_ThreadAlert(self->thread_id);
697 Tcl_ConditionWait(cond, mutex, NULL);
698 Tcl_MutexUnlock(mutex);
699 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000700}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000701#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000702
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000703
Guido van Rossum18468821994-06-20 07:49:28 +0000704/** Tcl Eval **/
705
Martin v. Löwisffad6332002-11-26 09:28:05 +0000706typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000707 PyObject_HEAD
708 Tcl_Obj *value;
709 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000710} PyTclObject;
711
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300712static PyObject *PyTclObject_Type;
713#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000714
715static PyObject *
716newPyTclObject(Tcl_Obj *arg)
717{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300719 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 if (self == NULL)
721 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200722 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000723 Tcl_IncrRefCount(arg);
724 self->value = arg;
725 self->string = NULL;
726 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000727}
728
729static void
730PyTclObject_dealloc(PyTclObject *self)
731{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200732 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000733 Tcl_DecrRefCount(self->value);
734 Py_XDECREF(self->string);
735 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200736 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000737}
738
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000739static char*
740PyTclObject_TclString(PyObject *self)
741{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000743}
744
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000745/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000746PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000747"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000748
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000749static PyObject *
750PyTclObject_string(PyTclObject *self, void *ignored)
751{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200753 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 if (!self->string)
755 return NULL;
756 }
757 Py_INCREF(self->string);
758 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000759}
760
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000761static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000762PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000763{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200764 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000765 Py_INCREF(self->string);
766 return self->string;
767 }
768 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200769 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000770}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000771
Martin v. Löwisffad6332002-11-26 09:28:05 +0000772static PyObject *
773PyTclObject_repr(PyTclObject *self)
774{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300775 PyObject *repr, *str = PyTclObject_str(self, NULL);
776 if (str == NULL)
777 return NULL;
778 repr = PyUnicode_FromFormat("<%s object: %R>",
779 self->value->typePtr->name, str);
780 Py_DECREF(str);
781 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000782}
783
Mark Dickinson211c6252009-02-01 10:28:51 +0000784#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
785
786static PyObject *
787PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000788{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000789 int result;
790 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000791
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000792 /* neither argument should be NULL, unless something's gone wrong */
793 if (self == NULL || other == NULL) {
794 PyErr_BadInternalCall();
795 return NULL;
796 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000798 /* both arguments should be instances of PyTclObject */
799 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
800 v = Py_NotImplemented;
801 goto finished;
802 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000803
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000804 if (self == other)
805 /* fast path when self and other are identical */
806 result = 0;
807 else
808 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
809 Tcl_GetString(((PyTclObject *)other)->value));
810 /* Convert return value to a Boolean */
811 switch (op) {
812 case Py_EQ:
813 v = TEST_COND(result == 0);
814 break;
815 case Py_NE:
816 v = TEST_COND(result != 0);
817 break;
818 case Py_LE:
819 v = TEST_COND(result <= 0);
820 break;
821 case Py_GE:
822 v = TEST_COND(result >= 0);
823 break;
824 case Py_LT:
825 v = TEST_COND(result < 0);
826 break;
827 case Py_GT:
828 v = TEST_COND(result > 0);
829 break;
830 default:
831 PyErr_BadArgument();
832 return NULL;
833 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000834 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000835 Py_INCREF(v);
836 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000837}
838
Martin v. Löwis39195712003-01-04 00:33:13 +0000839PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
840
Martin v. Löwisffad6332002-11-26 09:28:05 +0000841static PyObject*
842get_typename(PyTclObject* obj, void* ignored)
843{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200844 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000845}
846
Martin v. Löwis39195712003-01-04 00:33:13 +0000847
Martin v. Löwisffad6332002-11-26 09:28:05 +0000848static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000849 {"typename", (getter)get_typename, NULL, get_typename__doc__},
850 {"string", (getter)PyTclObject_string, NULL,
851 PyTclObject_string__doc__},
852 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000853};
854
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300855static PyType_Slot PyTclObject_Type_slots[] = {
856 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
857 {Py_tp_repr, (reprfunc)PyTclObject_repr},
858 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200859 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300860 {Py_tp_richcompare, PyTclObject_richcompare},
861 {Py_tp_getset, PyTclObject_getsetlist},
862 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000863};
864
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300865static PyType_Spec PyTclObject_Type_spec = {
866 "_tkinter.Tcl_Obj",
867 sizeof(PyTclObject),
868 0,
869 Py_TPFLAGS_DEFAULT,
870 PyTclObject_Type_slots,
871};
872
873
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300874#if PY_SIZE_MAX > INT_MAX
875#define CHECK_STRING_LENGTH(s) do { \
876 if (s != NULL && strlen(s) >= INT_MAX) { \
877 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
878 return NULL; \
879 } } while(0)
880#else
881#define CHECK_STRING_LENGTH(s)
882#endif
883
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000884static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000885AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000886{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000887 Tcl_Obj *result;
888 long longVal;
889 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000890
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200891 if (PyBytes_Check(value)) {
892 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
893 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
894 return NULL;
895 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300896 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200897 (int)PyBytes_GET_SIZE(value));
898 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000899 else if (PyBool_Check(value))
900 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
901 else if (PyLong_CheckExact(value) &&
902 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
903 !overflow)) {
904 /* If there is an overflow in the long conversion,
905 fall through to default object handling. */
906 return Tcl_NewLongObj(longVal);
907 }
908 else if (PyFloat_Check(value))
909 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300910 else if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300911 Tcl_Obj **argv;
912 Py_ssize_t size, i;
913
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300914 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300915 if (size == 0)
916 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300917 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300918 PyErr_SetString(PyExc_OverflowError,
919 PyTuple_Check(value) ? "tuple is too long" :
920 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300921 return NULL;
922 }
Victor Stinneree6c3c72014-09-11 17:50:21 +0200923 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
924 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +0200925 PyErr_NoMemory();
926 return NULL;
927 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300928 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300929 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200930 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200931 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000932 return result;
933 }
934 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200935 void *inbuf;
936 Py_ssize_t size;
937 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000938 Tcl_UniChar *outbuf = NULL;
939 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200940 size_t allocsize;
941
942 if (PyUnicode_READY(value) == -1)
943 return NULL;
944
945 inbuf = PyUnicode_DATA(value);
946 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300947 if (size == 0)
948 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300949 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
950 PyErr_SetString(PyExc_OverflowError, "string is too long");
951 return NULL;
952 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200953 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200954 if (kind == sizeof(Tcl_UniChar))
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200955 return Tcl_NewUnicodeObj(inbuf, (int)size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200956 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200957 outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000958 /* Else overflow occurred, and we take the next exit */
959 if (!outbuf) {
960 PyErr_NoMemory();
961 return NULL;
962 }
963 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200964 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
965 /* We cannot test for sizeof(Tcl_UniChar) directly,
966 so we test for UTF-8 size instead. */
967#if TCL_UTF_MAX == 3
968 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000969 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200970 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100971 "character U+%x is above the range "
972 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100973 ch);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200974 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000975 return NULL;
976 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300977#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200978 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000979 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200980 result = Tcl_NewUnicodeObj(outbuf, (int)size);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200981 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000982 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000983 }
984 else if(PyTclObject_Check(value)) {
985 Tcl_Obj *v = ((PyTclObject*)value)->value;
986 Tcl_IncrRefCount(v);
987 return v;
988 }
989 else {
990 PyObject *v = PyObject_Str(value);
991 if (!v)
992 return 0;
993 result = AsObj(v);
994 Py_DECREF(v);
995 return result;
996 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000997}
998
Martin v. Löwisffad6332002-11-26 09:28:05 +0000999static PyObject*
1000FromObj(PyObject* tkapp, Tcl_Obj *value)
1001{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001002 PyObject *result = NULL;
1003 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001004
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001005 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001006 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001007 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001008
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001009 if (value->typePtr == app->BooleanType) {
1010 result = value->internalRep.longValue ? Py_True : Py_False;
1011 Py_INCREF(result);
1012 return result;
1013 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001014
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001015 if (value->typePtr == app->ByteArrayType) {
1016 int size;
1017 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1018 return PyBytes_FromStringAndSize(data, size);
1019 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001020
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001021 if (value->typePtr == app->DoubleType) {
1022 return PyFloat_FromDouble(value->internalRep.doubleValue);
1023 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001024
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001025 if (value->typePtr == app->IntType) {
1026 return PyLong_FromLong(value->internalRep.longValue);
1027 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001028
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001029 if (value->typePtr == app->ListType) {
1030 int size;
1031 int i, status;
1032 PyObject *elem;
1033 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001034
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001035 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1036 if (status == TCL_ERROR)
1037 return Tkinter_Error(tkapp);
1038 result = PyTuple_New(size);
1039 if (!result)
1040 return NULL;
1041 for (i = 0; i < size; i++) {
1042 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1043 value, i, &tcl_elem);
1044 if (status == TCL_ERROR) {
1045 Py_DECREF(result);
1046 return Tkinter_Error(tkapp);
1047 }
1048 elem = FromObj(tkapp, tcl_elem);
1049 if (!elem) {
1050 Py_DECREF(result);
1051 return NULL;
1052 }
1053 PyTuple_SetItem(result, i, elem);
1054 }
1055 return result;
1056 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001057
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001058 if (value->typePtr == app->ProcBodyType) {
1059 /* fall through: return tcl object. */
1060 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001061
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001062 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001063 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001064 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001065 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001066 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001067
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001068 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001069}
1070
Benjamin Peterson5879d412009-03-30 14:51:56 +00001071#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001072/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001073TCL_DECLARE_MUTEX(call_mutex)
1074
1075typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001076 Tcl_Event ev; /* Must be first */
1077 TkappObject *self;
1078 PyObject *args;
1079 int flags;
1080 PyObject **res;
1081 PyObject **exc_type, **exc_value, **exc_tb;
1082 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001083} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001084#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001085
1086void
1087Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001088{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001089 int i;
1090 for (i = 0; i < objc; i++)
1091 Tcl_DecrRefCount(objv[i]);
1092 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001093 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001094}
Guido van Rossum18468821994-06-20 07:49:28 +00001095
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001096/* Convert Python objects to Tcl objects. This must happen in the
1097 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001098
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001099static Tcl_Obj**
1100Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1101{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001102 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001103 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001104 if (args == NULL)
1105 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001106
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001107 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001108 objv[0] = AsObj(args);
1109 if (objv[0] == 0)
1110 goto finally;
1111 objc = 1;
1112 Tcl_IncrRefCount(objv[0]);
1113 }
1114 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001115 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001116
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001117 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001118 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001119 PyErr_SetString(PyExc_OverflowError,
1120 PyTuple_Check(args) ? "tuple is too long" :
1121 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001122 return NULL;
1123 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001124 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001125 if (objv == NULL) {
1126 PyErr_NoMemory();
1127 objc = 0;
1128 goto finally;
1129 }
1130 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001131
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001132 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001133 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001134 if (v == Py_None) {
1135 objc = i;
1136 break;
1137 }
1138 objv[i] = AsObj(v);
1139 if (!objv[i]) {
1140 /* Reset objc, so it attempts to clear
1141 objects only up to i. */
1142 objc = i;
1143 goto finally;
1144 }
1145 Tcl_IncrRefCount(objv[i]);
1146 }
1147 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001148 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001149 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001150finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001151 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001152 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001153}
Guido van Rossum212643f1998-04-29 16:22:14 +00001154
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001155/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001156
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001157static PyObject*
1158Tkapp_CallResult(TkappObject *self)
1159{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001160 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001161 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001162 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001163 /* Not sure whether the IncrRef is necessary, but something
1164 may overwrite the interpreter result while we are
1165 converting it. */
1166 Tcl_IncrRefCount(value);
1167 res = FromObj((PyObject*)self, value);
1168 Tcl_DecrRefCount(value);
1169 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001170 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001171 }
1172 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001173}
Guido van Rossum632de272000-03-29 00:19:50 +00001174
Benjamin Peterson5879d412009-03-30 14:51:56 +00001175#ifdef WITH_THREAD
1176
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001177/* Tkapp_CallProc is the event procedure that is executed in the context of
1178 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1179 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001180
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001181static int
1182Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1183{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001184 Tcl_Obj *objStore[ARGSZ];
1185 Tcl_Obj **objv;
1186 int objc;
1187 int i;
1188 ENTER_PYTHON
1189 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1190 if (!objv) {
1191 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1192 *(e->res) = NULL;
1193 }
1194 LEAVE_PYTHON
1195 if (!objv)
1196 goto done;
1197 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1198 ENTER_PYTHON
1199 if (i == TCL_ERROR) {
1200 *(e->res) = NULL;
1201 *(e->exc_type) = NULL;
1202 *(e->exc_tb) = NULL;
1203 *(e->exc_value) = PyObject_CallFunction(
1204 Tkinter_TclError, "s",
1205 Tcl_GetStringResult(e->self->interp));
1206 }
1207 else {
1208 *(e->res) = Tkapp_CallResult(e->self);
1209 }
1210 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001212 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001213done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001214 /* Wake up calling thread. */
1215 Tcl_MutexLock(&call_mutex);
1216 Tcl_ConditionNotify(e->done);
1217 Tcl_MutexUnlock(&call_mutex);
1218 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001219}
1220
Benjamin Peterson5879d412009-03-30 14:51:56 +00001221#endif
1222
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001223/* This is the main entry point for calling a Tcl command.
1224 It supports three cases, with regard to threading:
1225 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1226 the context of the calling thread.
1227 2. Tcl is threaded, caller of the command is in the interpreter thread:
1228 Execute the command in the calling thread. Since the Tcl lock will
1229 not be used, we can merge that with case 1.
1230 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1231 the interpreter thread. Allocation of Tcl objects needs to occur in the
1232 interpreter thread, so we ship the PyObject* args to the target thread,
1233 and perform processing there. */
1234
1235static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001236Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001237{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001238 Tcl_Obj *objStore[ARGSZ];
1239 Tcl_Obj **objv = NULL;
1240 int objc, i;
1241 PyObject *res = NULL;
1242 TkappObject *self = (TkappObject*)selfptr;
1243 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001244
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001245 /* If args is a single tuple, replace with contents of tuple */
1246 if (1 == PyTuple_Size(args)){
1247 PyObject* item = PyTuple_GetItem(args, 0);
1248 if (PyTuple_Check(item))
1249 args = item;
1250 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001251#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001252 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1253 /* We cannot call the command directly. Instead, we must
1254 marshal the parameters to the interpreter thread. */
1255 Tkapp_CallEvent *ev;
1256 Tcl_Condition cond = NULL;
1257 PyObject *exc_type, *exc_value, *exc_tb;
1258 if (!WaitForMainloop(self))
1259 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001260 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1261 if (ev == NULL) {
1262 PyErr_NoMemory();
1263 return NULL;
1264 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001265 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1266 ev->self = self;
1267 ev->args = args;
1268 ev->res = &res;
1269 ev->exc_type = &exc_type;
1270 ev->exc_value = &exc_value;
1271 ev->exc_tb = &exc_tb;
1272 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001273
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001274 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001275
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001276 if (res == NULL) {
1277 if (exc_type)
1278 PyErr_Restore(exc_type, exc_value, exc_tb);
1279 else
1280 PyErr_SetObject(Tkinter_TclError, exc_value);
1281 }
1282 Tcl_ConditionFinalize(&cond);
1283 }
1284 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001285#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001286 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001287
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001288 objv = Tkapp_CallArgs(args, objStore, &objc);
1289 if (!objv)
1290 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001291
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001292 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001293
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001294 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001295
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001296 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001298 if (i == TCL_ERROR)
1299 Tkinter_Error(selfptr);
1300 else
1301 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001302
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001303 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001304
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001305 Tkapp_CallDeallocArgs(objv, objStore, objc);
1306 }
1307 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001308}
1309
1310
1311static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001312Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001313{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001314 char *script;
1315 PyObject *res = NULL;
1316 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001317
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001318 if (!PyArg_ParseTuple(args, "s:eval", &script))
1319 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001320
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001321 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001322 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001323
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001324 ENTER_TCL
1325 err = Tcl_Eval(Tkapp_Interp(self), script);
1326 ENTER_OVERLAP
1327 if (err == TCL_ERROR)
1328 res = Tkinter_Error(self);
1329 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001330 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001331 LEAVE_OVERLAP_TCL
1332 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001333}
1334
1335static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001336Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001337{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001338 char *fileName;
1339 PyObject *res = NULL;
1340 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001341
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001342 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1343 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001344
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001345 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001348 ENTER_TCL
1349 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1350 ENTER_OVERLAP
1351 if (err == TCL_ERROR)
1352 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001353 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001354 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001355 LEAVE_OVERLAP_TCL
1356 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001357}
1358
1359static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001360Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001361{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001362 char *script;
1363 PyObject *res = NULL;
1364 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001365
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001366 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001367 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001368
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001369 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001370 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001372 ENTER_TCL
1373 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1374 ENTER_OVERLAP
1375 if (err == TCL_ERROR)
1376 res = Tkinter_Error(self);
1377 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001378 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001379 LEAVE_OVERLAP_TCL
1380 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001381}
1382
1383static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001384Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001385{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001386 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001388 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1389 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001390 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001391 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001393 ENTER_TCL
1394 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1395 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001396
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001397 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001398}
1399
Barry Warsawfa701a81997-01-16 00:15:11 +00001400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001401
Guido van Rossum18468821994-06-20 07:49:28 +00001402/** Tcl Variable **/
1403
Benjamin Peterson5879d412009-03-30 14:51:56 +00001404typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1405
1406#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001407TCL_DECLARE_MUTEX(var_mutex)
1408
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001409typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001410 Tcl_Event ev; /* must be first */
1411 PyObject *self;
1412 PyObject *args;
1413 int flags;
1414 EventFunc func;
1415 PyObject **res;
1416 PyObject **exc_type;
1417 PyObject **exc_val;
1418 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001419} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001420#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001421
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001422static int
1423varname_converter(PyObject *in, void *_out)
1424{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001425 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001426 char **out = (char**)_out;
1427 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001428 if (PyBytes_Size(in) > INT_MAX) {
1429 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1430 return 0;
1431 }
1432 s = PyBytes_AsString(in);
Victor Stinner706768c2014-08-16 01:03:39 +02001433 if (strlen(s) != (size_t)PyBytes_Size(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001434 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001435 return 0;
1436 }
1437 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001438 return 1;
1439 }
1440 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001441 Py_ssize_t size;
1442 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001443 if (s == NULL) {
1444 return 0;
1445 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001446 if (size > INT_MAX) {
1447 PyErr_SetString(PyExc_OverflowError, "string is too long");
1448 return 0;
1449 }
Victor Stinner706768c2014-08-16 01:03:39 +02001450 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001451 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001452 return 0;
1453 }
1454 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001455 return 1;
1456 }
1457 if (PyTclObject_Check(in)) {
1458 *out = PyTclObject_TclString(in);
1459 return 1;
1460 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001461 PyErr_Format(PyExc_TypeError,
1462 "must be str, bytes or Tcl_Obj, not %.50s",
1463 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001464 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001465}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001466
Benjamin Peterson5879d412009-03-30 14:51:56 +00001467#ifdef WITH_THREAD
1468
Martin v. Löwis59683e82008-06-13 07:50:45 +00001469static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001470var_perform(VarEvent *ev)
1471{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001472 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1473 if (!*(ev->res)) {
1474 PyObject *exc, *val, *tb;
1475 PyErr_Fetch(&exc, &val, &tb);
1476 PyErr_NormalizeException(&exc, &val, &tb);
1477 *(ev->exc_type) = exc;
1478 *(ev->exc_val) = val;
1479 Py_DECREF(tb);
1480 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001481
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001482}
1483
1484static int
1485var_proc(VarEvent* ev, int flags)
1486{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001487 ENTER_PYTHON
1488 var_perform(ev);
1489 Tcl_MutexLock(&var_mutex);
1490 Tcl_ConditionNotify(ev->cond);
1491 Tcl_MutexUnlock(&var_mutex);
1492 LEAVE_PYTHON
1493 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001494}
1495
Benjamin Peterson5879d412009-03-30 14:51:56 +00001496#endif
1497
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001498static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001499var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001500{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001501#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001502 TkappObject *self = (TkappObject*)selfptr;
1503 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001504 VarEvent *ev;
1505 PyObject *res, *exc_type, *exc_val;
1506 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001508 /* The current thread is not the interpreter thread. Marshal
1509 the call to the interpreter thread, then wait for
1510 completion. */
1511 if (!WaitForMainloop(self))
1512 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001513
Serhiy Storchaka07940882014-09-11 10:38:54 +03001514 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1515 if (ev == NULL) {
1516 PyErr_NoMemory();
1517 return NULL;
1518 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001519 ev->self = selfptr;
1520 ev->args = args;
1521 ev->flags = flags;
1522 ev->func = func;
1523 ev->res = &res;
1524 ev->exc_type = &exc_type;
1525 ev->exc_val = &exc_val;
1526 ev->cond = &cond;
1527 ev->ev.proc = (Tcl_EventProc*)var_proc;
1528 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1529 Tcl_ConditionFinalize(&cond);
1530 if (!res) {
1531 PyErr_SetObject(exc_type, exc_val);
1532 Py_DECREF(exc_type);
1533 Py_DECREF(exc_val);
1534 return NULL;
1535 }
1536 return res;
1537 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001538#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001539 /* Tcl is not threaded, or this is the interpreter thread. */
1540 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001541}
1542
Guido van Rossum18468821994-06-20 07:49:28 +00001543static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001544SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001545{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001546 char *name1, *name2;
1547 PyObject *newValue;
1548 PyObject *res = NULL;
1549 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001550
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001551 switch (PyTuple_GET_SIZE(args)) {
1552 case 2:
1553 if (!PyArg_ParseTuple(args, "O&O:setvar",
1554 varname_converter, &name1, &newValue))
1555 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001556 /* XXX Acquire tcl lock??? */
1557 newval = AsObj(newValue);
1558 if (newval == NULL)
1559 return NULL;
1560 ENTER_TCL
1561 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1562 newval, flags);
1563 ENTER_OVERLAP
1564 if (!ok)
1565 Tkinter_Error(self);
1566 else {
1567 res = Py_None;
1568 Py_INCREF(res);
1569 }
1570 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001571 break;
1572 case 3:
1573 if (!PyArg_ParseTuple(args, "ssO:setvar",
1574 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001575 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001576 CHECK_STRING_LENGTH(name1);
1577 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001578 /* XXX must hold tcl lock already??? */
1579 newval = AsObj(newValue);
1580 ENTER_TCL
1581 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1582 ENTER_OVERLAP
1583 if (!ok)
1584 Tkinter_Error(self);
1585 else {
1586 res = Py_None;
1587 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001588 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001589 LEAVE_OVERLAP_TCL
1590 break;
1591 default:
1592 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1593 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001594 }
1595 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001596}
1597
1598static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001599Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001600{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001601 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001602}
1603
1604static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001605Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001606{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001607 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001608}
1609
Barry Warsawfa701a81997-01-16 00:15:11 +00001610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001611
Guido van Rossum18468821994-06-20 07:49:28 +00001612static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001613GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001614{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001615 char *name1, *name2=NULL;
1616 PyObject *res = NULL;
1617 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001619 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1620 varname_converter, &name1, &name2))
1621 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001622
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001623 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001624 ENTER_TCL
1625 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1626 ENTER_OVERLAP
1627 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001628 PyErr_SetString(Tkinter_TclError,
1629 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001630 } else {
1631 if (((TkappObject*)self)->wantobjects) {
1632 res = FromObj(self, tres);
1633 }
1634 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001635 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001636 }
1637 }
1638 LEAVE_OVERLAP_TCL
1639 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001640}
1641
1642static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001643Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001644{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001645 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001646}
1647
1648static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001649Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001650{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001651 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001652}
1653
Barry Warsawfa701a81997-01-16 00:15:11 +00001654
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001655
Guido van Rossum18468821994-06-20 07:49:28 +00001656static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001657UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001658{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001659 char *name1, *name2=NULL;
1660 int code;
1661 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001662
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001663 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1664 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001665
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001666 CHECK_STRING_LENGTH(name1);
1667 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001668 ENTER_TCL
1669 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1670 ENTER_OVERLAP
1671 if (code == TCL_ERROR)
1672 res = Tkinter_Error(self);
1673 else {
1674 Py_INCREF(Py_None);
1675 res = Py_None;
1676 }
1677 LEAVE_OVERLAP_TCL
1678 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001679}
1680
1681static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001682Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001683{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001684 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001685}
1686
1687static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001688Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001689{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001690 return var_invoke(UnsetVar, self, args,
1691 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001692}
1693
Barry Warsawfa701a81997-01-16 00:15:11 +00001694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001695
Guido van Rossum18468821994-06-20 07:49:28 +00001696/** Tcl to Python **/
1697
1698static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001699Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001700{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001701 char *s;
1702 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001703
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001704 if (PyTuple_Size(args) == 1) {
1705 PyObject* o = PyTuple_GetItem(args, 0);
1706 if (PyLong_Check(o)) {
1707 Py_INCREF(o);
1708 return o;
1709 }
1710 }
1711 if (!PyArg_ParseTuple(args, "s:getint", &s))
1712 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001713 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001714 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1715 return Tkinter_Error(self);
1716 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001717}
1718
1719static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001720Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001721{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001722 char *s;
1723 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001724
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001725 if (PyTuple_Size(args) == 1) {
1726 PyObject *o = PyTuple_GetItem(args, 0);
1727 if (PyFloat_Check(o)) {
1728 Py_INCREF(o);
1729 return o;
1730 }
1731 }
1732 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1733 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001734 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001735 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1736 return Tkinter_Error(self);
1737 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001738}
1739
1740static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001741Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001742{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001743 char *s;
1744 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001745
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001746 if (PyTuple_Size(args) == 1) {
1747 PyObject *o = PyTuple_GetItem(args, 0);
1748 if (PyLong_Check(o)) {
1749 Py_INCREF(o);
1750 return o;
1751 }
1752 }
1753 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1754 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001755 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001756 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1757 return Tkinter_Error(self);
1758 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001759}
1760
1761static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001762Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001763{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001764 char *s;
1765 PyObject *res = NULL;
1766 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001767
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001768 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1769 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001770
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001771 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001772 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001773
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001774 ENTER_TCL
1775 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1776 ENTER_OVERLAP
1777 if (retval == TCL_ERROR)
1778 res = Tkinter_Error(self);
1779 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001780 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001781 LEAVE_OVERLAP_TCL
1782 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001783}
1784
1785static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001786Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001787{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001788 char *s;
1789 PyObject *res = NULL;
1790 int retval;
1791 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001792
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001793 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1794 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001795
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001796 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001797 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001798
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001799 ENTER_TCL
1800 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1801 ENTER_OVERLAP
1802 if (retval == TCL_ERROR)
1803 res = Tkinter_Error(self);
1804 else
1805 res = Py_BuildValue("l", v);
1806 LEAVE_OVERLAP_TCL
1807 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001808}
1809
1810static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001811Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001812{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001813 char *s;
1814 PyObject *res = NULL;
1815 double v;
1816 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001817
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001818 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1819 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001820 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001821 CHECK_TCL_APPARTMENT;
1822 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1823 ENTER_TCL
1824 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1825 ENTER_OVERLAP
1826 PyFPE_END_PROTECT(retval)
1827 if (retval == TCL_ERROR)
1828 res = Tkinter_Error(self);
1829 else
1830 res = Py_BuildValue("d", v);
1831 LEAVE_OVERLAP_TCL
1832 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001833}
1834
1835static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001836Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001837{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001838 char *s;
1839 PyObject *res = NULL;
1840 int retval;
1841 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001842
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001843 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1844 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001845 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001846 CHECK_TCL_APPARTMENT;
1847 ENTER_TCL
1848 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1849 ENTER_OVERLAP
1850 if (retval == TCL_ERROR)
1851 res = Tkinter_Error(self);
1852 else
1853 res = Py_BuildValue("i", v);
1854 LEAVE_OVERLAP_TCL
1855 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001856}
1857
Barry Warsawfa701a81997-01-16 00:15:11 +00001858
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001859
Guido van Rossum18468821994-06-20 07:49:28 +00001860static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001861Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001862{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001863 char *list;
1864 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03001865 const char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001866 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001867 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001868
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001869 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1870 return NULL;
1871 if (PyTclObject_Check(arg)) {
1872 int objc;
1873 Tcl_Obj **objv;
1874 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1875 ((PyTclObject*)arg)->value,
1876 &objc, &objv) == TCL_ERROR) {
1877 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001878 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001879 if (!(v = PyTuple_New(objc)))
1880 return NULL;
1881 for (i = 0; i < objc; i++) {
1882 PyObject *s = FromObj(self, objv[i]);
1883 if (!s || PyTuple_SetItem(v, i, s)) {
1884 Py_DECREF(v);
1885 return NULL;
1886 }
1887 }
1888 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001889 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001890 if (PyTuple_Check(arg)) {
1891 Py_INCREF(arg);
1892 return arg;
1893 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001894 if (PyList_Check(arg)) {
1895 return PySequence_Tuple(arg);
1896 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001897
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001898 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1899 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001900
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001901 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001902 if (Tcl_SplitList(Tkapp_Interp(self), list,
1903 &argc, &argv) == TCL_ERROR) {
1904 PyMem_Free(list);
1905 return Tkinter_Error(self);
1906 }
Guido van Rossum18468821994-06-20 07:49:28 +00001907
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001908 if (!(v = PyTuple_New(argc)))
1909 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001910
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001911 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001912 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001913 if (!s || PyTuple_SetItem(v, i, s)) {
1914 Py_DECREF(v);
1915 v = NULL;
1916 goto finally;
1917 }
1918 }
Guido van Rossum18468821994-06-20 07:49:28 +00001919
Barry Warsawfa701a81997-01-16 00:15:11 +00001920 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001921 ckfree(FREECAST argv);
1922 PyMem_Free(list);
1923 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001924}
1925
1926static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001927Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001928{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001929 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001930 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001931
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001932 if (!PyArg_ParseTuple(args, "O:split", &arg))
1933 return NULL;
1934 if (PyTclObject_Check(arg)) {
1935 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1936 int objc;
1937 Tcl_Obj **objv;
1938 int i;
1939 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1940 &objc, &objv) == TCL_ERROR) {
1941 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001942 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001943 if (objc == 0)
1944 return PyUnicode_FromString("");
1945 if (objc == 1)
1946 return FromObj(self, objv[0]);
1947 if (!(v = PyTuple_New(objc)))
1948 return NULL;
1949 for (i = 0; i < objc; i++) {
1950 PyObject *s = FromObj(self, objv[i]);
1951 if (!s || PyTuple_SetItem(v, i, s)) {
1952 Py_DECREF(v);
1953 return NULL;
1954 }
1955 }
1956 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001957 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001958 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001959 return SplitObj(arg);
1960
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001961 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1962 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001963 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001964 v = Split(list);
1965 PyMem_Free(list);
1966 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001967}
1968
Barry Warsawfa701a81997-01-16 00:15:11 +00001969
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001970
Guido van Rossum18468821994-06-20 07:49:28 +00001971/** Tcl Command **/
1972
Guido van Rossum00d93061998-05-28 23:06:38 +00001973/* Client data struct */
1974typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001975 PyObject *self;
1976 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001977} PythonCmd_ClientData;
1978
1979static int
Fred Drake509d79a2000-07-08 04:04:38 +00001980PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001981{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001982 errorInCmd = 1;
1983 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1984 LEAVE_PYTHON
1985 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001986}
1987
Guido van Rossum18468821994-06-20 07:49:28 +00001988/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001989 * function or method.
1990 */
Guido van Rossum18468821994-06-20 07:49:28 +00001991static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03001992PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001993{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001994 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001995 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001996 int i, rv;
1997 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001998
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001999 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002000
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002001 /* TBD: no error checking here since we know, via the
2002 * Tkapp_CreateCommand() that the client data is a two-tuple
2003 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002004 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002005
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002006 /* Create argument list (argv1, ..., argvN) */
2007 if (!(arg = PyTuple_New(argc - 1)))
2008 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002010 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002011 PyObject *s = unicodeFromTclString(argv[i + 1]);
2012 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002013 Py_DECREF(arg);
2014 return PythonCmd_Error(interp);
2015 }
2016 }
2017 res = PyEval_CallObject(func, arg);
2018 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002019
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002020 if (res == NULL)
2021 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002022
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002023 obj_res = AsObj(res);
2024 if (obj_res == NULL) {
2025 Py_DECREF(res);
2026 return PythonCmd_Error(interp);
2027 }
2028 else {
2029 Tcl_SetObjResult(interp, obj_res);
2030 rv = TCL_OK;
2031 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002032
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002033 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002034
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002035 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002036
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002037 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002038}
2039
2040static void
Fred Drake509d79a2000-07-08 04:04:38 +00002041PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002042{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002043 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002044
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002045 ENTER_PYTHON
2046 Py_XDECREF(data->self);
2047 Py_XDECREF(data->func);
2048 PyMem_DEL(data);
2049 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002050}
2051
Barry Warsawfa701a81997-01-16 00:15:11 +00002052
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002053
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002054
Benjamin Peterson5879d412009-03-30 14:51:56 +00002055#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002056TCL_DECLARE_MUTEX(command_mutex)
2057
2058typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002059 Tcl_Event ev;
2060 Tcl_Interp* interp;
2061 char *name;
2062 int create;
2063 int *status;
2064 ClientData *data;
2065 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002066} CommandEvent;
2067
2068static int
2069Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002070{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002071 if (ev->create)
2072 *ev->status = Tcl_CreateCommand(
2073 ev->interp, ev->name, PythonCmd,
2074 ev->data, PythonCmdDelete) == NULL;
2075 else
2076 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2077 Tcl_MutexLock(&command_mutex);
2078 Tcl_ConditionNotify(ev->done);
2079 Tcl_MutexUnlock(&command_mutex);
2080 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002081}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002082#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002083
2084static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002085Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002086{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002087 TkappObject *self = (TkappObject*)selfptr;
2088 PythonCmd_ClientData *data;
2089 char *cmdName;
2090 PyObject *func;
2091 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002092
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002093 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2094 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002095 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002096 if (!PyCallable_Check(func)) {
2097 PyErr_SetString(PyExc_TypeError, "command not callable");
2098 return NULL;
2099 }
Guido van Rossum18468821994-06-20 07:49:28 +00002100
Martin v. Löwisa9656492003-03-30 08:44:58 +00002101#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002102 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2103 !WaitForMainloop(self))
2104 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002105#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002106
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002107 data = PyMem_NEW(PythonCmd_ClientData, 1);
2108 if (!data)
2109 return PyErr_NoMemory();
2110 Py_INCREF(self);
2111 Py_INCREF(func);
2112 data->self = selfptr;
2113 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002114#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2116 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002117 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2118 if (ev == NULL) {
2119 PyErr_NoMemory();
2120 PyMem_DEL(data);
2121 return NULL;
2122 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002123 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2124 ev->interp = self->interp;
2125 ev->create = 1;
2126 ev->name = cmdName;
2127 ev->data = (ClientData)data;
2128 ev->status = &err;
2129 ev->done = &cond;
2130 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2131 Tcl_ConditionFinalize(&cond);
2132 }
2133 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002134#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002135 {
2136 ENTER_TCL
2137 err = Tcl_CreateCommand(
2138 Tkapp_Interp(self), cmdName, PythonCmd,
2139 (ClientData)data, PythonCmdDelete) == NULL;
2140 LEAVE_TCL
2141 }
2142 if (err) {
2143 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2144 PyMem_DEL(data);
2145 return NULL;
2146 }
Guido van Rossum18468821994-06-20 07:49:28 +00002147
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002148 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002149}
2150
Barry Warsawfa701a81997-01-16 00:15:11 +00002151
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002152
Guido van Rossum18468821994-06-20 07:49:28 +00002153static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002154Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002155{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002156 TkappObject *self = (TkappObject*)selfptr;
2157 char *cmdName;
2158 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002159
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2161 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002162 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002163
2164#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002165 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2166 Tcl_Condition cond = NULL;
2167 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002168 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2169 if (ev == NULL) {
2170 PyErr_NoMemory();
2171 return NULL;
2172 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002173 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2174 ev->interp = self->interp;
2175 ev->create = 0;
2176 ev->name = cmdName;
2177 ev->status = &err;
2178 ev->done = &cond;
2179 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2180 &command_mutex);
2181 Tcl_ConditionFinalize(&cond);
2182 }
2183 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002184#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002185 {
2186 ENTER_TCL
2187 err = Tcl_DeleteCommand(self->interp, cmdName);
2188 LEAVE_TCL
2189 }
2190 if (err == -1) {
2191 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2192 return NULL;
2193 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002194 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002195}
2196
Barry Warsawfa701a81997-01-16 00:15:11 +00002197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002198
Guido van Rossum00d93061998-05-28 23:06:38 +00002199#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002200/** File Handler **/
2201
Guido van Rossum00d93061998-05-28 23:06:38 +00002202typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002203 PyObject *func;
2204 PyObject *file;
2205 int id;
2206 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002207} FileHandler_ClientData;
2208
2209static FileHandler_ClientData *HeadFHCD;
2210
2211static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002212NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002213{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002214 FileHandler_ClientData *p;
2215 p = PyMem_NEW(FileHandler_ClientData, 1);
2216 if (p != NULL) {
2217 Py_XINCREF(func);
2218 Py_XINCREF(file);
2219 p->func = func;
2220 p->file = file;
2221 p->id = id;
2222 p->next = HeadFHCD;
2223 HeadFHCD = p;
2224 }
2225 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002226}
2227
2228static void
Fred Drake509d79a2000-07-08 04:04:38 +00002229DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002230{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002231 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002232
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002233 pp = &HeadFHCD;
2234 while ((p = *pp) != NULL) {
2235 if (p->id == id) {
2236 *pp = p->next;
2237 Py_XDECREF(p->func);
2238 Py_XDECREF(p->file);
2239 PyMem_DEL(p);
2240 }
2241 else
2242 pp = &p->next;
2243 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002244}
2245
Guido van Rossuma597dde1995-01-10 20:56:29 +00002246static void
Fred Drake509d79a2000-07-08 04:04:38 +00002247FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002248{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002249 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2250 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002251
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002252 ENTER_PYTHON
2253 func = data->func;
2254 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002255
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002256 arg = Py_BuildValue("(Oi)", file, (long) mask);
2257 res = PyEval_CallObject(func, arg);
2258 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002260 if (res == NULL) {
2261 errorInCmd = 1;
2262 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2263 }
2264 Py_XDECREF(res);
2265 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002266}
2267
Guido van Rossum18468821994-06-20 07:49:28 +00002268static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002269Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2270 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002271{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002272 FileHandler_ClientData *data;
2273 PyObject *file, *func;
2274 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002275
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002276 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2277 &file, &mask, &func))
2278 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002280 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002282 tfile = PyObject_AsFileDescriptor(file);
2283 if (tfile < 0)
2284 return NULL;
2285 if (!PyCallable_Check(func)) {
2286 PyErr_SetString(PyExc_TypeError, "bad argument list");
2287 return NULL;
2288 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002289
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002290 data = NewFHCD(func, file, tfile);
2291 if (data == NULL)
2292 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002293
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002294 /* Ought to check for null Tcl_File object... */
2295 ENTER_TCL
2296 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2297 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002298 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002299}
2300
2301static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002302Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002303{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002304 PyObject *file;
2305 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002306
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002307 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2308 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002309
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002310 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002312 tfile = PyObject_AsFileDescriptor(file);
2313 if (tfile < 0)
2314 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002316 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002317
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002318 /* Ought to check for null Tcl_File object... */
2319 ENTER_TCL
2320 Tcl_DeleteFileHandler(tfile);
2321 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002322 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002323}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002324#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002326
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002327/**** Tktt Object (timer token) ****/
2328
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002329static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002330
Guido van Rossum00d93061998-05-28 23:06:38 +00002331typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002332 PyObject_HEAD
2333 Tcl_TimerToken token;
2334 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002335} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002336
2337static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002338Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002339{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002340 TkttObject *v = (TkttObject *)self;
2341 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002343 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2344 return NULL;
2345 if (v->token != NULL) {
2346 Tcl_DeleteTimerHandler(v->token);
2347 v->token = NULL;
2348 }
2349 if (func != NULL) {
2350 v->func = NULL;
2351 Py_DECREF(func);
2352 Py_DECREF(v); /* See Tktt_New() */
2353 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002354 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002355}
2356
2357static PyMethodDef Tktt_methods[] =
2358{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002359 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2360 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002361};
2362
2363static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002364Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002365{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002366 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002367
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002368 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002369 if (v == NULL)
2370 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002371 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002373 Py_INCREF(func);
2374 v->token = NULL;
2375 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002377 /* Extra reference, deleted when called or when handler is deleted */
2378 Py_INCREF(v);
2379 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002380}
2381
2382static void
Fred Drake509d79a2000-07-08 04:04:38 +00002383Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002384{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002385 TkttObject *v = (TkttObject *)self;
2386 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002387 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002389 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002391 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002392 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002393}
2394
Guido van Rossum597ac201998-05-12 14:36:19 +00002395static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002396Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002397{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002398 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002399 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2400 v,
2401 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002402}
2403
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002404static PyType_Slot Tktt_Type_slots[] = {
2405 {Py_tp_dealloc, Tktt_Dealloc},
2406 {Py_tp_repr, Tktt_Repr},
2407 {Py_tp_methods, Tktt_methods},
2408 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002409};
2410
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002411static PyType_Spec Tktt_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002412 "_tkinter.tktimertoken",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002413 sizeof(TkttObject),
2414 0,
2415 Py_TPFLAGS_DEFAULT,
2416 Tktt_Type_slots,
2417};
Barry Warsawfa701a81997-01-16 00:15:11 +00002418
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002419
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002420/** Timer Handler **/
2421
2422static void
Fred Drake509d79a2000-07-08 04:04:38 +00002423TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002424{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002425 TkttObject *v = (TkttObject *)clientData;
2426 PyObject *func = v->func;
2427 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002429 if (func == NULL)
2430 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002431
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002432 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002433
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002434 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002435
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002436 res = PyEval_CallObject(func, NULL);
2437 Py_DECREF(func);
2438 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002439
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002440 if (res == NULL) {
2441 errorInCmd = 1;
2442 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2443 }
2444 else
2445 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002446
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002447 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002448}
2449
2450static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002451Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002452{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002453 int milliseconds;
2454 PyObject *func;
2455 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002456
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002457 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2458 &milliseconds, &func))
2459 return NULL;
2460 if (!PyCallable_Check(func)) {
2461 PyErr_SetString(PyExc_TypeError, "bad argument list");
2462 return NULL;
2463 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002464
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002465 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002466
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002467 v = Tktt_New(func);
2468 if (v) {
2469 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2470 (ClientData)v);
2471 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002473 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002474}
2475
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002476
Guido van Rossum18468821994-06-20 07:49:28 +00002477/** Event Loop **/
2478
Guido van Rossum18468821994-06-20 07:49:28 +00002479static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002480Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002481{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002482 int threshold = 0;
2483 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002484#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002485 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002486#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002488 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2489 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002490
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002491 CHECK_TCL_APPARTMENT;
2492 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002494 quitMainLoop = 0;
2495 while (Tk_GetNumMainWindows() > threshold &&
2496 !quitMainLoop &&
2497 !errorInCmd)
2498 {
2499 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002500
2501#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002502 if (self->threaded) {
2503 /* Allow other Python threads to run. */
2504 ENTER_TCL
2505 result = Tcl_DoOneEvent(0);
2506 LEAVE_TCL
2507 }
2508 else {
2509 Py_BEGIN_ALLOW_THREADS
2510 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2511 tcl_tstate = tstate;
2512 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2513 tcl_tstate = NULL;
2514 if(tcl_lock)PyThread_release_lock(tcl_lock);
2515 if (result == 0)
2516 Sleep(Tkinter_busywaitinterval);
2517 Py_END_ALLOW_THREADS
2518 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002519#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002520 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002521#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002522
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002523 if (PyErr_CheckSignals() != 0) {
2524 self->dispatching = 0;
2525 return NULL;
2526 }
2527 if (result < 0)
2528 break;
2529 }
2530 self->dispatching = 0;
2531 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002532
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002533 if (errorInCmd) {
2534 errorInCmd = 0;
2535 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2536 excInCmd = valInCmd = trbInCmd = NULL;
2537 return NULL;
2538 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002539 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002540}
2541
2542static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002543Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002544{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002545 int flags = 0;
2546 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002548 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2549 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002551 ENTER_TCL
2552 rv = Tcl_DoOneEvent(flags);
2553 LEAVE_TCL
2554 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002555}
2556
2557static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002558Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002559{
2560
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002561 if (!PyArg_ParseTuple(args, ":quit"))
2562 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002564 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002565 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002566}
2567
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002568static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002569Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002570{
2571
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002572 if (!PyArg_ParseTuple(args, ":interpaddr"))
2573 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002574
Victor Stinnere1040e22013-09-05 00:22:24 +02002575 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002576}
2577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002578static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002579Tkapp_TkInit(PyObject *self, PyObject *args)
2580{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002581 Tcl_Interp *interp = Tkapp_Interp(self);
2582 const char * _tk_exists = NULL;
2583 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002584
Guilherme Polob681df42009-02-09 22:33:59 +00002585#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002586 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2587 * first call failed.
2588 * To avoid the deadlock, we just refuse the second call through
2589 * a static variable.
2590 */
2591 if (tk_load_failed) {
2592 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2593 return NULL;
2594 }
Guilherme Polob681df42009-02-09 22:33:59 +00002595#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002596
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002597 /* We want to guard against calling Tk_Init() multiple times */
2598 CHECK_TCL_APPARTMENT;
2599 ENTER_TCL
2600 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2601 ENTER_OVERLAP
2602 if (err == TCL_ERROR) {
2603 /* This sets an exception, but we cannot return right
2604 away because we need to exit the overlap first. */
2605 Tkinter_Error(self);
2606 } else {
2607 _tk_exists = Tkapp_Result(self);
2608 }
2609 LEAVE_OVERLAP_TCL
2610 if (err == TCL_ERROR) {
2611 return NULL;
2612 }
2613 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2614 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002615 PyErr_SetString(Tkinter_TclError,
2616 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002617#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002618 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002619#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002620 return NULL;
2621 }
2622 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002623 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002624}
Barry Warsawfa701a81997-01-16 00:15:11 +00002625
Martin v. Löwisffad6332002-11-26 09:28:05 +00002626static PyObject *
2627Tkapp_WantObjects(PyObject *self, PyObject *args)
2628{
2629
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002630 int wantobjects = -1;
2631 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2632 return NULL;
2633 if (wantobjects == -1)
2634 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2635 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002636
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002637 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002638}
2639
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002640static PyObject *
2641Tkapp_WillDispatch(PyObject *self, PyObject *args)
2642{
2643
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002644 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002645
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002646 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002647}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002648
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002649
Guido van Rossum18468821994-06-20 07:49:28 +00002650/**** Tkapp Method List ****/
2651
2652static PyMethodDef Tkapp_methods[] =
2653{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002654 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2655 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2656 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002657 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002658 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2659 {"record", Tkapp_Record, METH_VARARGS},
2660 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2661 {"setvar", Tkapp_SetVar, METH_VARARGS},
2662 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2663 {"getvar", Tkapp_GetVar, METH_VARARGS},
2664 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2665 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2666 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2667 {"getint", Tkapp_GetInt, METH_VARARGS},
2668 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2669 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2670 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2671 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2672 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2673 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2674 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2675 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2677 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002678#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002679 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2680 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002681#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002682 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2683 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2684 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2685 {"quit", Tkapp_Quit, METH_VARARGS},
2686 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2687 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2688 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002689};
2690
Barry Warsawfa701a81997-01-16 00:15:11 +00002691
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002692
Guido van Rossum18468821994-06-20 07:49:28 +00002693/**** Tkapp Type Methods ****/
2694
2695static void
Fred Drake509d79a2000-07-08 04:04:38 +00002696Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002697{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002698 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002699 /*CHECK_TCL_APPARTMENT;*/
2700 ENTER_TCL
2701 Tcl_DeleteInterp(Tkapp_Interp(self));
2702 LEAVE_TCL
2703 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002704 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002705 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002706}
2707
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002708static PyType_Slot Tkapp_Type_slots[] = {
2709 {Py_tp_dealloc, Tkapp_Dealloc},
2710 {Py_tp_methods, Tkapp_methods},
2711 {0, 0}
2712};
2713
2714
2715static PyType_Spec Tkapp_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002716 "_tkinter.tkapp",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002717 sizeof(TkappObject),
2718 0,
2719 Py_TPFLAGS_DEFAULT,
2720 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002721};
2722
Barry Warsawfa701a81997-01-16 00:15:11 +00002723
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002724
Guido van Rossum18468821994-06-20 07:49:28 +00002725/**** Tkinter Module ****/
2726
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002727typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002728 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002729 Py_ssize_t size; /* current size */
2730 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002731} FlattenContext;
2732
2733static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002734_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002735{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002736 /* expand tuple to hold (at least) size new items.
2737 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002738
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002739 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002742 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002743
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002744 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002745
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002746 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002747}
2748
2749static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002750_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002751{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002752 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002753
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002754 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002755
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002756 if (depth > 1000) {
2757 PyErr_SetString(PyExc_ValueError,
2758 "nesting too deep in _flatten");
2759 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002760 } else if (PyTuple_Check(item) || PyList_Check(item)) {
2761 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002762 /* preallocate (assume no nesting) */
2763 if (context->size + size > context->maxsize &&
2764 !_bump(context, size))
2765 return 0;
2766 /* copy items to output tuple */
2767 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002768 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002769 if (PyList_Check(o) || PyTuple_Check(o)) {
2770 if (!_flatten1(context, o, depth + 1))
2771 return 0;
2772 } else if (o != Py_None) {
2773 if (context->size + 1 > context->maxsize &&
2774 !_bump(context, 1))
2775 return 0;
2776 Py_INCREF(o);
2777 PyTuple_SET_ITEM(context->tuple,
2778 context->size++, o);
2779 }
2780 }
2781 } else {
2782 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2783 return 0;
2784 }
2785 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002786}
2787
2788static PyObject *
2789Tkinter_Flatten(PyObject* self, PyObject* args)
2790{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002791 FlattenContext context;
2792 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002793
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2795 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002796
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002797 context.maxsize = PySequence_Size(item);
2798 if (context.maxsize < 0)
2799 return NULL;
2800 if (context.maxsize == 0)
2801 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002802
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002803 context.tuple = PyTuple_New(context.maxsize);
2804 if (!context.tuple)
2805 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002806
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002807 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002808
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002809 if (!_flatten1(&context, item,0))
2810 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002811
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002812 if (_PyTuple_Resize(&context.tuple, context.size))
2813 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002814
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002815 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002816}
2817
Guido van Rossum18468821994-06-20 07:49:28 +00002818static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002819Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002820{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002821 char *screenName = NULL;
2822 char *baseName = NULL; /* XXX this is not used anymore;
2823 try getting rid of it. */
2824 char *className = NULL;
2825 int interactive = 0;
Serhiy Storchaka9e7cbda2014-05-28 16:57:55 +03002826 int wantobjects = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002827 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2828 int sync = 0; /* pass -sync to wish */
2829 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002830
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002831 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002832
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002833 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2834 &screenName, &baseName, &className,
2835 &interactive, &wantobjects, &wantTk,
2836 &sync, &use))
2837 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002838 CHECK_STRING_LENGTH(screenName);
2839 CHECK_STRING_LENGTH(baseName);
2840 CHECK_STRING_LENGTH(className);
2841 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00002842
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002843 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002844 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002845 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002846}
2847
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002848static PyObject *
2849Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2850{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002851 int new_val;
2852 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2853 return NULL;
2854 if (new_val < 0) {
2855 PyErr_SetString(PyExc_ValueError,
2856 "busywaitinterval must be >= 0");
2857 return NULL;
2858 }
2859 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002860 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002861}
2862
2863static char setbusywaitinterval_doc[] =
2864"setbusywaitinterval(n) -> None\n\
2865\n\
2866Set the busy-wait interval in milliseconds between successive\n\
2867calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2868It should be set to a divisor of the maximum time between\n\
2869frames in an animation.";
2870
2871static PyObject *
2872Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2873{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002874 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002875}
2876
2877static char getbusywaitinterval_doc[] =
2878"getbusywaitinterval() -> int\n\
2879\n\
2880Return the current busy-wait interval between successive\n\
2881calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2882
Guido van Rossum18468821994-06-20 07:49:28 +00002883static PyMethodDef moduleMethods[] =
2884{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002885 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2886 {"create", Tkinter_Create, METH_VARARGS},
2887 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2888 setbusywaitinterval_doc},
2889 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2890 METH_NOARGS, getbusywaitinterval_doc},
2891 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002892};
2893
Guido van Rossum7bf15641998-05-22 18:28:17 +00002894#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002895
2896static int stdin_ready = 0;
2897
Guido van Rossumad4db171998-06-13 13:56:28 +00002898#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002899static void
Fred Drake509d79a2000-07-08 04:04:38 +00002900MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002901{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002902 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002903}
Guido van Rossumad4db171998-06-13 13:56:28 +00002904#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002905
Martin v. Löwisa9656492003-03-30 08:44:58 +00002906#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002907static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002908#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002909
Guido van Rossum18468821994-06-20 07:49:28 +00002910static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002911EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002912{
Guido van Rossumad4db171998-06-13 13:56:28 +00002913#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002914 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002915#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002916#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002917 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002918#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002919 stdin_ready = 0;
2920 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002921#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002922 tfile = fileno(stdin);
2923 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002924#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002925 while (!errorInCmd && !stdin_ready) {
2926 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002927#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002928 if (_kbhit()) {
2929 stdin_ready = 1;
2930 break;
2931 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002932#endif
2933#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002934 Py_BEGIN_ALLOW_THREADS
2935 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2936 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002937
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002938 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002939
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002940 tcl_tstate = NULL;
2941 if(tcl_lock)PyThread_release_lock(tcl_lock);
2942 if (result == 0)
2943 Sleep(Tkinter_busywaitinterval);
2944 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002945#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002946 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002947#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002948
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002949 if (result < 0)
2950 break;
2951 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002952#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002953 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002954#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002955 if (errorInCmd) {
2956 errorInCmd = 0;
2957 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2958 excInCmd = valInCmd = trbInCmd = NULL;
2959 PyErr_Print();
2960 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002961#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002962 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002963#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002964 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002965}
Guido van Rossum18468821994-06-20 07:49:28 +00002966
Guido van Rossum00d93061998-05-28 23:06:38 +00002967#endif
2968
Guido van Rossum7bf15641998-05-22 18:28:17 +00002969static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002970EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002971{
Guido van Rossum00d93061998-05-28 23:06:38 +00002972#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002973 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002974#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002975 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002976#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002977 PyOS_InputHook = EventHook;
2978 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002979#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002980}
2981
2982static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002983DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002984{
Guido van Rossum00d93061998-05-28 23:06:38 +00002985#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002986 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2987 PyOS_InputHook = NULL;
2988 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002989#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002990}
2991
Barry Warsawfa701a81997-01-16 00:15:11 +00002992
Martin v. Löwis1a214512008-06-11 05:26:20 +00002993static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002994 PyModuleDef_HEAD_INIT,
2995 "_tkinter",
2996 NULL,
2997 -1,
2998 moduleMethods,
2999 NULL,
3000 NULL,
3001 NULL,
3002 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003003};
3004
Mark Hammond62b1ab12002-07-23 06:31:15 +00003005PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003006PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003007{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003008 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003009
Guido van Rossum00d93061998-05-28 23:06:38 +00003010#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003011 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003012 if (tcl_lock == NULL)
3013 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003014#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003016 m = PyModule_Create(&_tkintermodule);
3017 if (m == NULL)
3018 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003019
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003020 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3021 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003022 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003023 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003024 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003025 Py_INCREF(o);
3026 if (PyModule_AddObject(m, "TclError", o)) {
3027 Py_DECREF(o);
3028 Py_DECREF(m);
3029 return NULL;
3030 }
3031 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003032
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003033 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3034 Py_DECREF(m);
3035 return NULL;
3036 }
3037 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3038 Py_DECREF(m);
3039 return NULL;
3040 }
3041 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3042 Py_DECREF(m);
3043 return NULL;
3044 }
3045 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3046 Py_DECREF(m);
3047 return NULL;
3048 }
3049 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3050 Py_DECREF(m);
3051 return NULL;
3052 }
3053 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3054 Py_DECREF(m);
3055 return NULL;
3056 }
3057 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3058 Py_DECREF(m);
3059 return NULL;
3060 }
3061 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3062 Py_DECREF(m);
3063 return NULL;
3064 }
3065 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3066 Py_DECREF(m);
3067 return NULL;
3068 }
3069 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3070 Py_DECREF(m);
3071 return NULL;
3072 }
3073 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3074 Py_DECREF(m);
3075 return NULL;
3076 }
3077
3078 o = PyType_FromSpec(&Tkapp_Type_spec);
3079 if (o == NULL) {
3080 Py_DECREF(m);
3081 return NULL;
3082 }
3083 if (PyModule_AddObject(m, "TkappType", o)) {
3084 Py_DECREF(o);
3085 Py_DECREF(m);
3086 return NULL;
3087 }
3088 Tkapp_Type = o;
3089
3090 o = PyType_FromSpec(&Tktt_Type_spec);
3091 if (o == NULL) {
3092 Py_DECREF(m);
3093 return NULL;
3094 }
3095 if (PyModule_AddObject(m, "TkttType", o)) {
3096 Py_DECREF(o);
3097 Py_DECREF(m);
3098 return NULL;
3099 }
3100 Tktt_Type = o;
3101
3102 o = PyType_FromSpec(&PyTclObject_Type_spec);
3103 if (o == NULL) {
3104 Py_DECREF(m);
3105 return NULL;
3106 }
3107 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3108 Py_DECREF(o);
3109 Py_DECREF(m);
3110 return NULL;
3111 }
3112 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003113
3114#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003115 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3116 * start waking up. Note that Tcl_FindExecutable will do this, this
3117 * code must be above it! The original warning from
3118 * tkMacOSXAppInit.c is copied below.
3119 *
3120 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3121 * Tcl interpreter for now. It probably should work to do this
3122 * in the other order, but for now it doesn't seem to.
3123 *
3124 */
3125 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003126#endif
3127
3128
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003129 /* This helps the dynamic loader; in Unicode aware Tcl versions
3130 it also helps Tcl find its encodings. */
3131 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3132 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003133 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003134 if (cexe)
3135 Tcl_FindExecutable(PyBytes_AsString(cexe));
3136 Py_XDECREF(cexe);
3137 Py_DECREF(uexe);
3138 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003139
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003140 if (PyErr_Occurred()) {
3141 Py_DECREF(m);
3142 return NULL;
3143 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003144
Guido van Rossum43ff8681998-07-14 18:02:13 +00003145#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003146 /* This was not a good idea; through <Destroy> bindings,
3147 Tcl_Finalize() may invoke Python code but at that point the
3148 interpreter and thread state have already been destroyed! */
3149 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003150#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003151 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003152}