blob: bef7837e7e6438267d635820571164678bd29a22 [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
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000012 Only Tcl/Tk 8.3.1 and later are supported. Older versions are not
13 supported. Use Python 2.6 or older if you cannot upgrade your
14 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
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Martin v. Löwis39195712003-01-04 00:33:13 +000036/* Allow using this code in Python 2.[12] */
37#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000038#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000039#endif
40
41#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000042#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000045#ifndef PyBool_Check
46#define PyBool_Check(o) 0
Christian Heimes217cfd12007-12-02 14:31:20 +000047#define PyBool_FromLong PyLong_FromLong
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000048#endif
49
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030050#define CHECK_SIZE(size, elemsize) \
51 ((size_t)(size) <= Py_MAX((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
52
Martin v. Löwis71e25a02002-10-01 18:08:06 +000053/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
54 making _tkinter correct for this API means to break earlier
55 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
56 earlier versions. Once Tcl releases before 8.4 don't need to be supported
57 anymore, this should go. */
58#define USE_COMPAT_CONST
59
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000060/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
61 it always; if Tcl is not threaded, the thread functions in
62 Tcl are empty. */
63#define TCL_THREADS
64
Jack Jansencb852442001-12-09 23:15:56 +000065#ifdef TK_FRAMEWORK
66#include <Tcl/tcl.h>
67#include <Tk/tk.h>
68#else
Guido van Rossum18468821994-06-20 07:49:28 +000069#include <tcl.h>
70#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000071#endif
Guido van Rossum18468821994-06-20 07:49:28 +000072
Guilherme Polo2d87e422009-04-10 22:19:09 +000073#include "tkinter.h"
74
Jason Tishlerbbe89612002-12-31 20:30:46 +000075/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000076#ifndef CONST84_RETURN
77#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000078#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000079#define CONST
80#endif
81
Guilherme Polo66917722009-02-09 22:35:27 +000082#if TK_VERSION_HEX < 0x08030102
83#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000084#endif
85
Jack Janseneddc1442003-11-20 01:44:59 +000086#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000087#define HAVE_CREATEFILEHANDLER
88#endif
89
Guido van Rossum00d93061998-05-28 23:06:38 +000090#ifdef HAVE_CREATEFILEHANDLER
91
Neal Norwitzd948a432006-01-08 01:08:55 +000092/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
93 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
94#ifndef TCL_UNIX_FD
95# ifdef TCL_WIN_SOCKET
96# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
97# else
98# define TCL_UNIX_FD 1
99# endif
100#endif
101
Guido van Rossum00d93061998-05-28 23:06:38 +0000102/* Tcl_CreateFileHandler() changed several times; these macros deal with the
103 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
104 Unix, only because Jack added it back); when available on Windows, it only
105 applies to sockets. */
106
Guido van Rossum7bf15641998-05-22 18:28:17 +0000107#ifdef MS_WINDOWS
108#define FHANDLETYPE TCL_WIN_SOCKET
109#else
110#define FHANDLETYPE TCL_UNIX_FD
111#endif
112
Guido van Rossum00d93061998-05-28 23:06:38 +0000113/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
114 which uses this to handle Tcl events while the user is typing commands. */
115
116#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000117#define WAIT_FOR_STDIN
118#endif
119
Guido van Rossum00d93061998-05-28 23:06:38 +0000120#endif /* HAVE_CREATEFILEHANDLER */
121
Guido van Rossumad4db171998-06-13 13:56:28 +0000122#ifdef MS_WINDOWS
123#include <conio.h>
124#define WAIT_FOR_STDIN
125#endif
126
Guido van Rossum00d93061998-05-28 23:06:38 +0000127#ifdef WITH_THREAD
128
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000129/* The threading situation is complicated. Tcl is not thread-safe, except
130 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000131
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300132 So we need to use a lock around all uses of Tcl. Previously, the
133 Python interpreter lock was used for this. However, this causes
134 problems when other Python threads need to run while Tcl is blocked
135 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000136
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300137 To solve this problem, a separate lock for Tcl is introduced.
138 Holding it is incompatible with holding Python's interpreter lock.
139 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000140
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300141 ENTER_TCL and LEAVE_TCL are brackets, just like
142 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
143 used whenever a call into Tcl is made that could call an event
144 handler, or otherwise affect the state of a Tcl interpreter. These
145 assume that the surrounding code has the Python interpreter lock;
146 inside the brackets, the Python interpreter lock has been released
147 and the lock for Tcl has been acquired.
148
149 Sometimes, it is necessary to have both the Python lock and the Tcl
150 lock. (For example, when transferring data from the Tcl
151 interpreter result to a Python string object.) This can be done by
152 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
153 reacquires the Python lock (and restores the thread state) but
154 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
155 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000156
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000157 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300158 handlers when the handler needs to use Python. Such event handlers
159 are entered while the lock for Tcl is held; the event handler
160 presumably needs to use Python. ENTER_PYTHON releases the lock for
161 Tcl and acquires the Python interpreter lock, restoring the
162 appropriate thread state, and LEAVE_PYTHON releases the Python
163 interpreter lock and re-acquires the lock for Tcl. It is okay for
164 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
165 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000166
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300167 These locks expand to several statements and brackets; they should
168 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000169
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300170 If Tcl is threaded, this approach won't work anymore. The Tcl
171 interpreter is only valid in the thread that created it, and all Tk
172 activity must happen in this thread, also. That means that the
173 mainloop must be invoked in the thread that created the
174 interpreter. Invoking commands from other threads is possible;
175 _tkinter will queue an event for the interpreter thread, which will
176 then execute the command and pass back the result. If the main
177 thread is not in the mainloop, and invoking commands causes an
178 exception; if the main loop is running but not processing events,
179 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000180
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300181 In addition, for a threaded Tcl, a single global tcl_tstate won't
182 be sufficient anymore, since multiple Tcl interpreters may
183 simultaneously dispatch in different threads. So we use the Tcl TLS
184 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000185
Guido van Rossum00d93061998-05-28 23:06:38 +0000186*/
187
Guido van Rossum65d5b571998-12-21 19:32:43 +0000188static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000189
190#ifdef TCL_THREADS
191static Tcl_ThreadDataKey state_key;
192typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300193#define tcl_tstate \
194 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000195#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000196static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000197#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000198
199#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000200 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
201 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
203#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300204 tcl_tstate = NULL; \
205 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000206
Guido van Rossum62320c91998-06-15 04:36:09 +0000207#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000208 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000209
210#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000211 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000212
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000213#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000214 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300215 if(tcl_lock) \
216 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000217
218#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000219 { PyThreadState *tstate = PyEval_SaveThread(); \
220 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000221
222#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000223 if (((TkappObject *)self)->threaded && \
224 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300225 PyErr_SetString(PyExc_RuntimeError, \
226 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000227 return 0; \
228 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000229
230#else
231
232#define ENTER_TCL
233#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000234#define ENTER_OVERLAP
235#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000236#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000237#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000238#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000239
240#endif
241
Guido van Rossum97867b21996-08-08 19:09:53 +0000242#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000243#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000244#endif
245
Guido van Rossum18468821994-06-20 07:49:28 +0000246/**** Tkapp Object Declaration ****/
247
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300248static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000249
Guido van Rossum00d93061998-05-28 23:06:38 +0000250typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000251 PyObject_HEAD
252 Tcl_Interp *interp;
253 int wantobjects;
254 int threaded; /* True if tcl_platform[threaded] */
255 Tcl_ThreadId thread_id;
256 int dispatching;
257 /* We cannot include tclInt.h, as this is internal.
258 So we cache interesting types here. */
259 Tcl_ObjType *BooleanType;
260 Tcl_ObjType *ByteArrayType;
261 Tcl_ObjType *DoubleType;
262 Tcl_ObjType *IntType;
263 Tcl_ObjType *ListType;
264 Tcl_ObjType *ProcBodyType;
265 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000266} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000267
Guido van Rossum18468821994-06-20 07:49:28 +0000268#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000269#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000270
Guido van Rossum35d43371997-08-02 00:09:09 +0000271#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000272(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000273
Barry Warsawfa701a81997-01-16 00:15:11 +0000274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275
Guido van Rossum18468821994-06-20 07:49:28 +0000276/**** Error Handling ****/
277
278static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000279static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000280static int errorInCmd = 0;
281static PyObject *excInCmd;
282static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000283static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000284
Guilherme Polob681df42009-02-09 22:33:59 +0000285#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000286static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000287#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000288
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000289
Guido van Rossum18468821994-06-20 07:49:28 +0000290static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000291Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000292{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000293 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
294 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000295}
296
Barry Warsawfa701a81997-01-16 00:15:11 +0000297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000298
Guido van Rossum18468821994-06-20 07:49:28 +0000299/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000300
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000301static int Tkinter_busywaitinterval = 20;
302
Guido van Rossum00d93061998-05-28 23:06:38 +0000303#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000304#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000305
Guido van Rossum00d93061998-05-28 23:06:38 +0000306/* Millisecond sleep() for Unix platforms. */
307
308static void
Fred Drake509d79a2000-07-08 04:04:38 +0000309Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000310{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000311 /* XXX Too bad if you don't have select(). */
312 struct timeval t;
313 t.tv_sec = milli/1000;
314 t.tv_usec = (milli%1000) * 1000;
315 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000316}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000317#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000318
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000319/* Wait up to 1s for the mainloop to come up. */
320
321static int
322WaitForMainloop(TkappObject* self)
323{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000324 int i;
325 for (i = 0; i < 10; i++) {
326 if (self->dispatching)
327 return 1;
328 Py_BEGIN_ALLOW_THREADS
329 Sleep(100);
330 Py_END_ALLOW_THREADS
331 }
332 if (self->dispatching)
333 return 1;
334 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
335 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000336}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000337#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000338
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000339
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000340
Guido van Rossum18468821994-06-20 07:49:28 +0000341#define ARGSZ 64
342
Barry Warsawfa701a81997-01-16 00:15:11 +0000343
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000344
Guido van Rossum18468821994-06-20 07:49:28 +0000345static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000346Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000347{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000348 int argc;
349 char **argv;
350 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000352 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300353 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000354 }
Guido van Rossum18468821994-06-20 07:49:28 +0000355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000356 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
357 /* Not a list.
358 * Could be a quoted string containing funnies, e.g. {"}.
359 * Return the string itself.
360 */
361 return PyUnicode_FromString(list);
362 }
Guido van Rossum18468821994-06-20 07:49:28 +0000363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000364 if (argc == 0)
365 v = PyUnicode_FromString("");
366 else if (argc == 1)
367 v = PyUnicode_FromString(argv[0]);
368 else if ((v = PyTuple_New(argc)) != NULL) {
369 int i;
370 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000372 for (i = 0; i < argc; i++) {
373 if ((w = Split(argv[i])) == NULL) {
374 Py_DECREF(v);
375 v = NULL;
376 break;
377 }
378 PyTuple_SetItem(v, i, w);
379 }
380 }
381 Tcl_Free(FREECAST argv);
382 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000383}
384
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300385/* In some cases, Tcl will still return strings that are supposed to
386 be lists. SplitObj walks through a nested tuple, finding string
387 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000388
Martin v. Löwis59683e82008-06-13 07:50:45 +0000389static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000390SplitObj(PyObject *arg)
391{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000392 if (PyTuple_Check(arg)) {
393 int i, size;
394 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000395
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000396 size = PyTuple_Size(arg);
397 result = NULL;
398 /* Recursively invoke SplitObj for all tuple items.
399 If this does not return a new object, no action is
400 needed. */
401 for(i = 0; i < size; i++) {
402 elem = PyTuple_GetItem(arg, i);
403 newelem = SplitObj(elem);
404 if (!newelem) {
405 Py_XDECREF(result);
406 return NULL;
407 }
408 if (!result) {
409 int k;
410 if (newelem == elem) {
411 Py_DECREF(newelem);
412 continue;
413 }
414 result = PyTuple_New(size);
415 if (!result)
416 return NULL;
417 for(k = 0; k < i; k++) {
418 elem = PyTuple_GetItem(arg, k);
419 Py_INCREF(elem);
420 PyTuple_SetItem(result, k, elem);
421 }
422 }
423 PyTuple_SetItem(result, i, newelem);
424 }
425 if (result)
426 return result;
427 /* Fall through, returning arg. */
428 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300429 else if (PyUnicode_Check(arg)) {
430 int argc;
431 char **argv;
432 char *list = PyUnicode_AsUTF8(arg);
433
434 if (list == NULL ||
435 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
436 Py_INCREF(arg);
437 return arg;
438 }
439 Tcl_Free(FREECAST argv);
440 if (argc > 1)
441 return Split(list);
442 /* Fall through, returning arg. */
443 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000444 else if (PyBytes_Check(arg)) {
445 int argc;
446 char **argv;
447 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000449 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
450 Py_INCREF(arg);
451 return arg;
452 }
453 Tcl_Free(FREECAST argv);
454 if (argc > 1)
455 return Split(PyBytes_AsString(arg));
456 /* Fall through, returning arg. */
457 }
458 Py_INCREF(arg);
459 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000460}
Barry Warsawfa701a81997-01-16 00:15:11 +0000461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000462
Guido van Rossum18468821994-06-20 07:49:28 +0000463/**** Tkapp Object ****/
464
465#ifndef WITH_APPINIT
466int
Fred Drake509d79a2000-07-08 04:04:38 +0000467Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000468{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000469 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000471 if (Tcl_Init(interp) == TCL_ERROR) {
472 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
473 return TCL_ERROR;
474 }
Guilherme Polob681df42009-02-09 22:33:59 +0000475
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000476 _tkinter_skip_tk_init = Tcl_GetVar(interp,
477 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
478 if (_tkinter_skip_tk_init != NULL &&
479 strcmp(_tkinter_skip_tk_init, "1") == 0) {
480 return TCL_OK;
481 }
Guilherme Polob681df42009-02-09 22:33:59 +0000482
483#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000484 if (tk_load_failed) {
485 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
486 return TCL_ERROR;
487 }
Guilherme Polob681df42009-02-09 22:33:59 +0000488#endif
489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000491#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000492 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000493#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000494 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
495 return TCL_ERROR;
496 }
Guilherme Polob681df42009-02-09 22:33:59 +0000497
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000498 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000499}
500#endif /* !WITH_APPINIT */
501
Guido van Rossum18468821994-06-20 07:49:28 +0000502
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000503
Barry Warsawfa701a81997-01-16 00:15:11 +0000504
505/* Initialize the Tk application; see the `main' function in
506 * `tkMain.c'.
507 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000508
Thomas Wouters58d05102000-07-24 14:43:35 +0000509static void EnableEventHook(void); /* Forward */
510static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000511
Barry Warsawfa701a81997-01-16 00:15:11 +0000512static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000513Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000514 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000515{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000516 TkappObject *v;
517 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000518
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300519 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000520 if (v == NULL)
521 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200522 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 v->interp = Tcl_CreateInterp();
525 v->wantobjects = wantobjects;
526 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
527 TCL_GLOBAL_ONLY) != NULL;
528 v->thread_id = Tcl_GetCurrentThread();
529 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000530
531#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000532 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300533 PyErr_SetString(PyExc_RuntimeError,
534 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000535 Py_DECREF(v);
536 return 0;
537 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000538#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000539#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540 if (v->threaded && tcl_lock) {
541 /* If Tcl is threaded, we don't need the lock. */
542 PyThread_free_lock(tcl_lock);
543 tcl_lock = NULL;
544 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000545#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000546
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 v->BooleanType = Tcl_GetObjType("boolean");
548 v->ByteArrayType = Tcl_GetObjType("bytearray");
549 v->DoubleType = Tcl_GetObjType("double");
550 v->IntType = Tcl_GetObjType("int");
551 v->ListType = Tcl_GetObjType("list");
552 v->ProcBodyType = Tcl_GetObjType("procbody");
553 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000554
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000555 /* Delete the 'exit' command, which can screw things up */
556 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000557
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000558 if (screenName != NULL)
559 Tcl_SetVar2(v->interp, "env", "DISPLAY",
560 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000561
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 if (interactive)
563 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
564 else
565 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 /* This is used to get the application class for Tk 4.1 and up */
568 argv0 = (char*)ckalloc(strlen(className) + 1);
569 if (!argv0) {
570 PyErr_NoMemory();
571 Py_DECREF(v);
572 return NULL;
573 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000574
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000575 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200576 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
577 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000578 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
579 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000580
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000581 if (! wantTk) {
582 Tcl_SetVar(v->interp,
583 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
584 }
Guilherme Polob681df42009-02-09 22:33:59 +0000585#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 else if (tk_load_failed) {
587 Tcl_SetVar(v->interp,
588 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
589 }
Guilherme Polob681df42009-02-09 22:33:59 +0000590#endif
David Aschere2b4b322004-02-18 05:59:53 +0000591
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000592 /* some initial arguments need to be in argv */
593 if (sync || use) {
594 char *args;
595 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000596
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000597 if (sync)
598 len += sizeof "-sync";
599 if (use)
600 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000602 args = (char*)ckalloc(len);
603 if (!args) {
604 PyErr_NoMemory();
605 Py_DECREF(v);
606 return NULL;
607 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000608
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 args[0] = '\0';
610 if (sync)
611 strcat(args, "-sync");
612 if (use) {
613 if (sync)
614 strcat(args, " ");
615 strcat(args, "-use ");
616 strcat(args, use);
617 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000619 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
620 ckfree(args);
621 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000622
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 if (Tcl_AppInit(v->interp) != TCL_OK) {
624 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000625#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000626 if (wantTk) {
627 const char *_tkinter_tk_failed;
628 _tkinter_tk_failed = Tcl_GetVar(v->interp,
629 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000631 if ( _tkinter_tk_failed != NULL &&
632 strcmp(_tkinter_tk_failed, "1") == 0) {
633 tk_load_failed = 1;
634 }
635 }
Guilherme Polob681df42009-02-09 22:33:59 +0000636#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 Py_DECREF((PyObject *)v);
638 return (TkappObject *)result;
639 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000640
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000643 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000644}
645
Barry Warsawfa701a81997-01-16 00:15:11 +0000646
Benjamin Peterson5879d412009-03-30 14:51:56 +0000647#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000648static void
649Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000651{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000652 Py_BEGIN_ALLOW_THREADS;
653 Tcl_MutexLock(mutex);
654 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
655 Tcl_ThreadAlert(self->thread_id);
656 Tcl_ConditionWait(cond, mutex, NULL);
657 Tcl_MutexUnlock(mutex);
658 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000659}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000660#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000661
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662
Guido van Rossum18468821994-06-20 07:49:28 +0000663/** Tcl Eval **/
664
Martin v. Löwisffad6332002-11-26 09:28:05 +0000665typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 PyObject_HEAD
667 Tcl_Obj *value;
668 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000669} PyTclObject;
670
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300671static PyObject *PyTclObject_Type;
672#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000673
674static PyObject *
675newPyTclObject(Tcl_Obj *arg)
676{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300678 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000679 if (self == NULL)
680 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200681 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 Tcl_IncrRefCount(arg);
683 self->value = arg;
684 self->string = NULL;
685 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000686}
687
688static void
689PyTclObject_dealloc(PyTclObject *self)
690{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200691 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000692 Tcl_DecrRefCount(self->value);
693 Py_XDECREF(self->string);
694 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200695 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000696}
697
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000698static char*
699PyTclObject_TclString(PyObject *self)
700{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000702}
703
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000704/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000705PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000706"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000707
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000708static PyObject *
709PyTclObject_string(PyTclObject *self, void *ignored)
710{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000711 char *s;
712 int len;
713 if (!self->string) {
714 s = Tcl_GetStringFromObj(self->value, &len);
715 self->string = PyUnicode_FromStringAndSize(s, len);
716 if (!self->string)
717 return NULL;
718 }
719 Py_INCREF(self->string);
720 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000721}
722
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000723static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000724PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000725{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000726 char *s;
727 int len;
728 if (self->string && PyUnicode_Check(self->string)) {
729 Py_INCREF(self->string);
730 return self->string;
731 }
732 /* XXX Could chache result if it is non-ASCII. */
733 s = Tcl_GetStringFromObj(self->value, &len);
734 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000735}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000736
Martin v. Löwisffad6332002-11-26 09:28:05 +0000737static PyObject *
738PyTclObject_repr(PyTclObject *self)
739{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000740 return PyUnicode_FromFormat("<%s object at %p>",
741 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000742}
743
Mark Dickinson211c6252009-02-01 10:28:51 +0000744#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
745
746static PyObject *
747PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000748{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 int result;
750 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000751
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752 /* neither argument should be NULL, unless something's gone wrong */
753 if (self == NULL || other == NULL) {
754 PyErr_BadInternalCall();
755 return NULL;
756 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000757
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000758 /* both arguments should be instances of PyTclObject */
759 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
760 v = Py_NotImplemented;
761 goto finished;
762 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000763
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000764 if (self == other)
765 /* fast path when self and other are identical */
766 result = 0;
767 else
768 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
769 Tcl_GetString(((PyTclObject *)other)->value));
770 /* Convert return value to a Boolean */
771 switch (op) {
772 case Py_EQ:
773 v = TEST_COND(result == 0);
774 break;
775 case Py_NE:
776 v = TEST_COND(result != 0);
777 break;
778 case Py_LE:
779 v = TEST_COND(result <= 0);
780 break;
781 case Py_GE:
782 v = TEST_COND(result >= 0);
783 break;
784 case Py_LT:
785 v = TEST_COND(result < 0);
786 break;
787 case Py_GT:
788 v = TEST_COND(result > 0);
789 break;
790 default:
791 PyErr_BadArgument();
792 return NULL;
793 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000794 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000795 Py_INCREF(v);
796 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000797}
798
Martin v. Löwis39195712003-01-04 00:33:13 +0000799PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
800
Martin v. Löwisffad6332002-11-26 09:28:05 +0000801static PyObject*
802get_typename(PyTclObject* obj, void* ignored)
803{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000804 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000805}
806
Martin v. Löwis39195712003-01-04 00:33:13 +0000807
Martin v. Löwisffad6332002-11-26 09:28:05 +0000808static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000809 {"typename", (getter)get_typename, NULL, get_typename__doc__},
810 {"string", (getter)PyTclObject_string, NULL,
811 PyTclObject_string__doc__},
812 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000813};
814
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300815static PyType_Slot PyTclObject_Type_slots[] = {
816 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
817 {Py_tp_repr, (reprfunc)PyTclObject_repr},
818 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200819 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300820 {Py_tp_richcompare, PyTclObject_richcompare},
821 {Py_tp_getset, PyTclObject_getsetlist},
822 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000823};
824
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300825static PyType_Spec PyTclObject_Type_spec = {
826 "_tkinter.Tcl_Obj",
827 sizeof(PyTclObject),
828 0,
829 Py_TPFLAGS_DEFAULT,
830 PyTclObject_Type_slots,
831};
832
833
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000834static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000835AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000836{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000837 Tcl_Obj *result;
838 long longVal;
839 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000840
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000841 if (PyBytes_Check(value))
842 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
843 PyBytes_GET_SIZE(value));
844 else if (PyBool_Check(value))
845 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
846 else if (PyLong_CheckExact(value) &&
847 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
848 !overflow)) {
849 /* If there is an overflow in the long conversion,
850 fall through to default object handling. */
851 return Tcl_NewLongObj(longVal);
852 }
853 else if (PyFloat_Check(value))
854 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
855 else if (PyTuple_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300856 Tcl_Obj **argv;
857 Py_ssize_t size, i;
858
859 size = PyTuple_Size(value);
860 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
861 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
862 return NULL;
863 }
864 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000865 if(!argv)
866 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300867 for (i = 0; i < size; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000868 argv[i] = AsObj(PyTuple_GetItem(value,i));
869 result = Tcl_NewListObj(PyTuple_Size(value), argv);
870 ckfree(FREECAST argv);
871 return result;
872 }
873 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200874 void *inbuf;
875 Py_ssize_t size;
876 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000877 Tcl_UniChar *outbuf = NULL;
878 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200879 size_t allocsize;
880
881 if (PyUnicode_READY(value) == -1)
882 return NULL;
883
884 inbuf = PyUnicode_DATA(value);
885 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300886 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
887 PyErr_SetString(PyExc_OverflowError, "string is too long");
888 return NULL;
889 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200890 kind = PyUnicode_KIND(value);
891 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
892 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000893 /* Else overflow occurred, and we take the next exit */
894 if (!outbuf) {
895 PyErr_NoMemory();
896 return NULL;
897 }
898 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200899 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
900 /* We cannot test for sizeof(Tcl_UniChar) directly,
901 so we test for UTF-8 size instead. */
902#if TCL_UTF_MAX == 3
903 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000904 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200905 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100906 "character U+%x is above the range "
907 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100908 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000909 ckfree(FREECAST outbuf);
910 return NULL;
911 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300912#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200913 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000914 }
915 result = Tcl_NewUnicodeObj(outbuf, size);
916 ckfree(FREECAST outbuf);
917 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000918 }
919 else if(PyTclObject_Check(value)) {
920 Tcl_Obj *v = ((PyTclObject*)value)->value;
921 Tcl_IncrRefCount(v);
922 return v;
923 }
924 else {
925 PyObject *v = PyObject_Str(value);
926 if (!v)
927 return 0;
928 result = AsObj(v);
929 Py_DECREF(v);
930 return result;
931 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000932}
933
Martin v. Löwisffad6332002-11-26 09:28:05 +0000934static PyObject*
935FromObj(PyObject* tkapp, Tcl_Obj *value)
936{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000937 PyObject *result = NULL;
938 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000939
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000940 if (value->typePtr == NULL) {
941 return PyUnicode_FromStringAndSize(value->bytes,
942 value->length);
943 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000944
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000945 if (value->typePtr == app->BooleanType) {
946 result = value->internalRep.longValue ? Py_True : Py_False;
947 Py_INCREF(result);
948 return result;
949 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000950
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000951 if (value->typePtr == app->ByteArrayType) {
952 int size;
953 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
954 return PyBytes_FromStringAndSize(data, size);
955 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000956
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000957 if (value->typePtr == app->DoubleType) {
958 return PyFloat_FromDouble(value->internalRep.doubleValue);
959 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000960
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000961 if (value->typePtr == app->IntType) {
962 return PyLong_FromLong(value->internalRep.longValue);
963 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000964
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000965 if (value->typePtr == app->ListType) {
966 int size;
967 int i, status;
968 PyObject *elem;
969 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000970
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000971 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
972 if (status == TCL_ERROR)
973 return Tkinter_Error(tkapp);
974 result = PyTuple_New(size);
975 if (!result)
976 return NULL;
977 for (i = 0; i < size; i++) {
978 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
979 value, i, &tcl_elem);
980 if (status == TCL_ERROR) {
981 Py_DECREF(result);
982 return Tkinter_Error(tkapp);
983 }
984 elem = FromObj(tkapp, tcl_elem);
985 if (!elem) {
986 Py_DECREF(result);
987 return NULL;
988 }
989 PyTuple_SetItem(result, i, elem);
990 }
991 return result;
992 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000993
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000994 if (value->typePtr == app->ProcBodyType) {
995 /* fall through: return tcl object. */
996 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000997
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000998 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200999#if TCL_UTF_MAX==3
1000 return PyUnicode_FromKindAndData(
1001 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
1002 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001003#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001004 return PyUnicode_FromKindAndData(
1005 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
1006 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001007#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001008 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001010 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001011}
1012
Benjamin Peterson5879d412009-03-30 14:51:56 +00001013#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001014/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001015TCL_DECLARE_MUTEX(call_mutex)
1016
1017typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001018 Tcl_Event ev; /* Must be first */
1019 TkappObject *self;
1020 PyObject *args;
1021 int flags;
1022 PyObject **res;
1023 PyObject **exc_type, **exc_value, **exc_tb;
1024 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001025} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001026#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001027
1028void
1029Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001030{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001031 int i;
1032 for (i = 0; i < objc; i++)
1033 Tcl_DecrRefCount(objv[i]);
1034 if (objv != objStore)
1035 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001036}
Guido van Rossum18468821994-06-20 07:49:28 +00001037
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001038/* Convert Python objects to Tcl objects. This must happen in the
1039 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001040
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001041static Tcl_Obj**
1042Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1043{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001044 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001045 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001046 if (args == NULL)
1047 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001048
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001049 else if (!PyTuple_Check(args)) {
1050 objv[0] = AsObj(args);
1051 if (objv[0] == 0)
1052 goto finally;
1053 objc = 1;
1054 Tcl_IncrRefCount(objv[0]);
1055 }
1056 else {
1057 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001058
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001059 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001060 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1061 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1062 return NULL;
1063 }
1064 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001065 if (objv == NULL) {
1066 PyErr_NoMemory();
1067 objc = 0;
1068 goto finally;
1069 }
1070 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001071
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001072 for (i = 0; i < objc; i++) {
1073 PyObject *v = PyTuple_GetItem(args, i);
1074 if (v == Py_None) {
1075 objc = i;
1076 break;
1077 }
1078 objv[i] = AsObj(v);
1079 if (!objv[i]) {
1080 /* Reset objc, so it attempts to clear
1081 objects only up to i. */
1082 objc = i;
1083 goto finally;
1084 }
1085 Tcl_IncrRefCount(objv[i]);
1086 }
1087 }
1088 *pobjc = objc;
1089 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001090finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001091 Tkapp_CallDeallocArgs(objv, objStore, objc);
1092 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001093}
Guido van Rossum212643f1998-04-29 16:22:14 +00001094
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001095/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001096
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001097static PyObject*
1098Tkapp_CallResult(TkappObject *self)
1099{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001100 PyObject *res = NULL;
1101 if(self->wantobjects) {
1102 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1103 /* Not sure whether the IncrRef is necessary, but something
1104 may overwrite the interpreter result while we are
1105 converting it. */
1106 Tcl_IncrRefCount(value);
1107 res = FromObj((PyObject*)self, value);
1108 Tcl_DecrRefCount(value);
1109 } else {
1110 const char *s = Tcl_GetStringResult(self->interp);
1111 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001112
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001113 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1114 }
1115 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001116}
Guido van Rossum632de272000-03-29 00:19:50 +00001117
Benjamin Peterson5879d412009-03-30 14:51:56 +00001118#ifdef WITH_THREAD
1119
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001120/* Tkapp_CallProc is the event procedure that is executed in the context of
1121 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1122 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001123
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001124static int
1125Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1126{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001127 Tcl_Obj *objStore[ARGSZ];
1128 Tcl_Obj **objv;
1129 int objc;
1130 int i;
1131 ENTER_PYTHON
1132 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1133 if (!objv) {
1134 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1135 *(e->res) = NULL;
1136 }
1137 LEAVE_PYTHON
1138 if (!objv)
1139 goto done;
1140 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1141 ENTER_PYTHON
1142 if (i == TCL_ERROR) {
1143 *(e->res) = NULL;
1144 *(e->exc_type) = NULL;
1145 *(e->exc_tb) = NULL;
1146 *(e->exc_value) = PyObject_CallFunction(
1147 Tkinter_TclError, "s",
1148 Tcl_GetStringResult(e->self->interp));
1149 }
1150 else {
1151 *(e->res) = Tkapp_CallResult(e->self);
1152 }
1153 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001154
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001155 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001156done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001157 /* Wake up calling thread. */
1158 Tcl_MutexLock(&call_mutex);
1159 Tcl_ConditionNotify(e->done);
1160 Tcl_MutexUnlock(&call_mutex);
1161 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001162}
1163
Benjamin Peterson5879d412009-03-30 14:51:56 +00001164#endif
1165
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001166/* This is the main entry point for calling a Tcl command.
1167 It supports three cases, with regard to threading:
1168 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1169 the context of the calling thread.
1170 2. Tcl is threaded, caller of the command is in the interpreter thread:
1171 Execute the command in the calling thread. Since the Tcl lock will
1172 not be used, we can merge that with case 1.
1173 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1174 the interpreter thread. Allocation of Tcl objects needs to occur in the
1175 interpreter thread, so we ship the PyObject* args to the target thread,
1176 and perform processing there. */
1177
1178static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001179Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001180{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001181 Tcl_Obj *objStore[ARGSZ];
1182 Tcl_Obj **objv = NULL;
1183 int objc, i;
1184 PyObject *res = NULL;
1185 TkappObject *self = (TkappObject*)selfptr;
1186 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001187
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001188 /* If args is a single tuple, replace with contents of tuple */
1189 if (1 == PyTuple_Size(args)){
1190 PyObject* item = PyTuple_GetItem(args, 0);
1191 if (PyTuple_Check(item))
1192 args = item;
1193 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001194#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001195 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1196 /* We cannot call the command directly. Instead, we must
1197 marshal the parameters to the interpreter thread. */
1198 Tkapp_CallEvent *ev;
1199 Tcl_Condition cond = NULL;
1200 PyObject *exc_type, *exc_value, *exc_tb;
1201 if (!WaitForMainloop(self))
1202 return NULL;
1203 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1204 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1205 ev->self = self;
1206 ev->args = args;
1207 ev->res = &res;
1208 ev->exc_type = &exc_type;
1209 ev->exc_value = &exc_value;
1210 ev->exc_tb = &exc_tb;
1211 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001212
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001213 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001214
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001215 if (res == NULL) {
1216 if (exc_type)
1217 PyErr_Restore(exc_type, exc_value, exc_tb);
1218 else
1219 PyErr_SetObject(Tkinter_TclError, exc_value);
1220 }
1221 Tcl_ConditionFinalize(&cond);
1222 }
1223 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001224#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001225 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001226
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001227 objv = Tkapp_CallArgs(args, objStore, &objc);
1228 if (!objv)
1229 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001230
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001231 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001232
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001233 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001234
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001235 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001236
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001237 if (i == TCL_ERROR)
1238 Tkinter_Error(selfptr);
1239 else
1240 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001241
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001242 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001243
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001244 Tkapp_CallDeallocArgs(objv, objStore, objc);
1245 }
1246 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001247}
1248
1249
1250static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001251Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001252{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001253 char *script;
1254 PyObject *res = NULL;
1255 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001257 if (!PyArg_ParseTuple(args, "s:eval", &script))
1258 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001260 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001262 ENTER_TCL
1263 err = Tcl_Eval(Tkapp_Interp(self), script);
1264 ENTER_OVERLAP
1265 if (err == TCL_ERROR)
1266 res = Tkinter_Error(self);
1267 else
1268 res = PyUnicode_FromString(Tkapp_Result(self));
1269 LEAVE_OVERLAP_TCL
1270 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001271}
1272
1273static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001274Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001275{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001276 char *fileName;
1277 PyObject *res = NULL;
1278 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001280 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1281 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001282
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001283 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001284
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001285 ENTER_TCL
1286 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1287 ENTER_OVERLAP
1288 if (err == TCL_ERROR)
1289 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001290
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001291 else
1292 res = PyUnicode_FromString(Tkapp_Result(self));
1293 LEAVE_OVERLAP_TCL
1294 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001295}
1296
1297static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001298Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001299{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001300 char *script;
1301 PyObject *res = NULL;
1302 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001303
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001304 if (!PyArg_ParseTuple(args, "s", &script))
1305 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001306
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001307 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001308
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001309 ENTER_TCL
1310 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1311 ENTER_OVERLAP
1312 if (err == TCL_ERROR)
1313 res = Tkinter_Error(self);
1314 else
1315 res = PyUnicode_FromString(Tkapp_Result(self));
1316 LEAVE_OVERLAP_TCL
1317 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001318}
1319
1320static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001321Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001322{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001323 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1326 return NULL;
1327 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001328
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001329 ENTER_TCL
1330 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1331 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001332
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001333 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001334}
1335
Barry Warsawfa701a81997-01-16 00:15:11 +00001336
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001337
Guido van Rossum18468821994-06-20 07:49:28 +00001338/** Tcl Variable **/
1339
Benjamin Peterson5879d412009-03-30 14:51:56 +00001340typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1341
1342#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001343TCL_DECLARE_MUTEX(var_mutex)
1344
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001345typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 Tcl_Event ev; /* must be first */
1347 PyObject *self;
1348 PyObject *args;
1349 int flags;
1350 EventFunc func;
1351 PyObject **res;
1352 PyObject **exc_type;
1353 PyObject **exc_val;
1354 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001355} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001356#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001357
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001358static int
1359varname_converter(PyObject *in, void *_out)
1360{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001361 char **out = (char**)_out;
1362 if (PyBytes_Check(in)) {
1363 *out = PyBytes_AsString(in);
1364 return 1;
1365 }
1366 if (PyUnicode_Check(in)) {
1367 *out = _PyUnicode_AsString(in);
1368 return 1;
1369 }
1370 if (PyTclObject_Check(in)) {
1371 *out = PyTclObject_TclString(in);
1372 return 1;
1373 }
1374 /* XXX: Should give diagnostics. */
1375 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001376}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001377
Benjamin Peterson5879d412009-03-30 14:51:56 +00001378#ifdef WITH_THREAD
1379
Martin v. Löwis59683e82008-06-13 07:50:45 +00001380static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001381var_perform(VarEvent *ev)
1382{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001383 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1384 if (!*(ev->res)) {
1385 PyObject *exc, *val, *tb;
1386 PyErr_Fetch(&exc, &val, &tb);
1387 PyErr_NormalizeException(&exc, &val, &tb);
1388 *(ev->exc_type) = exc;
1389 *(ev->exc_val) = val;
1390 Py_DECREF(tb);
1391 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001392
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001393}
1394
1395static int
1396var_proc(VarEvent* ev, int flags)
1397{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001398 ENTER_PYTHON
1399 var_perform(ev);
1400 Tcl_MutexLock(&var_mutex);
1401 Tcl_ConditionNotify(ev->cond);
1402 Tcl_MutexUnlock(&var_mutex);
1403 LEAVE_PYTHON
1404 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001405}
1406
Benjamin Peterson5879d412009-03-30 14:51:56 +00001407#endif
1408
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001409static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001410var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001411{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001412#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001413 TkappObject *self = (TkappObject*)selfptr;
1414 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1415 TkappObject *self = (TkappObject*)selfptr;
1416 VarEvent *ev;
1417 PyObject *res, *exc_type, *exc_val;
1418 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001420 /* The current thread is not the interpreter thread. Marshal
1421 the call to the interpreter thread, then wait for
1422 completion. */
1423 if (!WaitForMainloop(self))
1424 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001426 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001427
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001428 ev->self = selfptr;
1429 ev->args = args;
1430 ev->flags = flags;
1431 ev->func = func;
1432 ev->res = &res;
1433 ev->exc_type = &exc_type;
1434 ev->exc_val = &exc_val;
1435 ev->cond = &cond;
1436 ev->ev.proc = (Tcl_EventProc*)var_proc;
1437 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1438 Tcl_ConditionFinalize(&cond);
1439 if (!res) {
1440 PyErr_SetObject(exc_type, exc_val);
1441 Py_DECREF(exc_type);
1442 Py_DECREF(exc_val);
1443 return NULL;
1444 }
1445 return res;
1446 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001447#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001448 /* Tcl is not threaded, or this is the interpreter thread. */
1449 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001450}
1451
Guido van Rossum18468821994-06-20 07:49:28 +00001452static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001453SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001454{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001455 char *name1, *name2;
1456 PyObject *newValue;
1457 PyObject *res = NULL;
1458 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001459
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001460 if (PyArg_ParseTuple(args, "O&O:setvar",
1461 varname_converter, &name1, &newValue)) {
1462 /* XXX Acquire tcl lock??? */
1463 newval = AsObj(newValue);
1464 if (newval == NULL)
1465 return NULL;
1466 ENTER_TCL
1467 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1468 newval, flags);
1469 ENTER_OVERLAP
1470 if (!ok)
1471 Tkinter_Error(self);
1472 else {
1473 res = Py_None;
1474 Py_INCREF(res);
1475 }
1476 LEAVE_OVERLAP_TCL
1477 }
1478 else {
1479 PyErr_Clear();
1480 if (PyArg_ParseTuple(args, "ssO:setvar",
1481 &name1, &name2, &newValue)) {
1482 /* XXX must hold tcl lock already??? */
1483 newval = AsObj(newValue);
1484 ENTER_TCL
1485 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1486 ENTER_OVERLAP
1487 if (!ok)
1488 Tkinter_Error(self);
1489 else {
1490 res = Py_None;
1491 Py_INCREF(res);
1492 }
1493 LEAVE_OVERLAP_TCL
1494 }
1495 else {
1496 return NULL;
1497 }
1498 }
1499 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001500}
1501
1502static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001503Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001504{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001505 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001506}
1507
1508static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001509Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001510{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001511 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001512}
1513
Barry Warsawfa701a81997-01-16 00:15:11 +00001514
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001515
Guido van Rossum18468821994-06-20 07:49:28 +00001516static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001517GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001518{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001519 char *name1, *name2=NULL;
1520 PyObject *res = NULL;
1521 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001522
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001523 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1524 varname_converter, &name1, &name2))
1525 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001526
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001527 ENTER_TCL
1528 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1529 ENTER_OVERLAP
1530 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001531 PyErr_SetString(Tkinter_TclError,
1532 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 } else {
1534 if (((TkappObject*)self)->wantobjects) {
1535 res = FromObj(self, tres);
1536 }
1537 else {
1538 res = PyUnicode_FromString(Tcl_GetString(tres));
1539 }
1540 }
1541 LEAVE_OVERLAP_TCL
1542 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001543}
1544
1545static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001546Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001547{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001548 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001549}
1550
1551static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001552Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001553{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001554 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001555}
1556
Barry Warsawfa701a81997-01-16 00:15:11 +00001557
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001558
Guido van Rossum18468821994-06-20 07:49:28 +00001559static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001560UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001561{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001562 char *name1, *name2=NULL;
1563 int code;
1564 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001565
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1567 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001568
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001569 ENTER_TCL
1570 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1571 ENTER_OVERLAP
1572 if (code == TCL_ERROR)
1573 res = Tkinter_Error(self);
1574 else {
1575 Py_INCREF(Py_None);
1576 res = Py_None;
1577 }
1578 LEAVE_OVERLAP_TCL
1579 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001580}
1581
1582static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001583Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001584{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001585 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001586}
1587
1588static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001589Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001590{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001591 return var_invoke(UnsetVar, self, args,
1592 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001593}
1594
Barry Warsawfa701a81997-01-16 00:15:11 +00001595
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001596
Guido van Rossum18468821994-06-20 07:49:28 +00001597/** Tcl to Python **/
1598
1599static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001600Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001601{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001602 char *s;
1603 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001605 if (PyTuple_Size(args) == 1) {
1606 PyObject* o = PyTuple_GetItem(args, 0);
1607 if (PyLong_Check(o)) {
1608 Py_INCREF(o);
1609 return o;
1610 }
1611 }
1612 if (!PyArg_ParseTuple(args, "s:getint", &s))
1613 return NULL;
1614 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1615 return Tkinter_Error(self);
1616 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001617}
1618
1619static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001620Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001621{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001622 char *s;
1623 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001625 if (PyTuple_Size(args) == 1) {
1626 PyObject *o = PyTuple_GetItem(args, 0);
1627 if (PyFloat_Check(o)) {
1628 Py_INCREF(o);
1629 return o;
1630 }
1631 }
1632 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1633 return NULL;
1634 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1635 return Tkinter_Error(self);
1636 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001637}
1638
1639static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001640Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001641{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001642 char *s;
1643 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001645 if (PyTuple_Size(args) == 1) {
1646 PyObject *o = PyTuple_GetItem(args, 0);
1647 if (PyLong_Check(o)) {
1648 Py_INCREF(o);
1649 return o;
1650 }
1651 }
1652 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1653 return NULL;
1654 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1655 return Tkinter_Error(self);
1656 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001657}
1658
1659static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001660Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001661{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001662 char *s;
1663 PyObject *res = NULL;
1664 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001666 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1667 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001669 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001670
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001671 ENTER_TCL
1672 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1673 ENTER_OVERLAP
1674 if (retval == TCL_ERROR)
1675 res = Tkinter_Error(self);
1676 else
1677 res = Py_BuildValue("s", Tkapp_Result(self));
1678 LEAVE_OVERLAP_TCL
1679 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001680}
1681
1682static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001683Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001684{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001685 char *s;
1686 PyObject *res = NULL;
1687 int retval;
1688 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001689
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001690 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1691 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001692
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001693 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001695 ENTER_TCL
1696 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1697 ENTER_OVERLAP
1698 if (retval == TCL_ERROR)
1699 res = Tkinter_Error(self);
1700 else
1701 res = Py_BuildValue("l", v);
1702 LEAVE_OVERLAP_TCL
1703 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001704}
1705
1706static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001707Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001708{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001709 char *s;
1710 PyObject *res = NULL;
1711 double v;
1712 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001713
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001714 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1715 return NULL;
1716 CHECK_TCL_APPARTMENT;
1717 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1718 ENTER_TCL
1719 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1720 ENTER_OVERLAP
1721 PyFPE_END_PROTECT(retval)
1722 if (retval == TCL_ERROR)
1723 res = Tkinter_Error(self);
1724 else
1725 res = Py_BuildValue("d", v);
1726 LEAVE_OVERLAP_TCL
1727 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001728}
1729
1730static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001731Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001732{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001733 char *s;
1734 PyObject *res = NULL;
1735 int retval;
1736 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001737
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1739 return NULL;
1740 CHECK_TCL_APPARTMENT;
1741 ENTER_TCL
1742 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1743 ENTER_OVERLAP
1744 if (retval == TCL_ERROR)
1745 res = Tkinter_Error(self);
1746 else
1747 res = Py_BuildValue("i", v);
1748 LEAVE_OVERLAP_TCL
1749 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001750}
1751
Barry Warsawfa701a81997-01-16 00:15:11 +00001752
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001753
Guido van Rossum18468821994-06-20 07:49:28 +00001754static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001755Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001756{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001757 char *list;
1758 int argc;
1759 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001760 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001761 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001762
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001763 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1764 return NULL;
1765 if (PyTclObject_Check(arg)) {
1766 int objc;
1767 Tcl_Obj **objv;
1768 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1769 ((PyTclObject*)arg)->value,
1770 &objc, &objv) == TCL_ERROR) {
1771 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001772 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001773 if (!(v = PyTuple_New(objc)))
1774 return NULL;
1775 for (i = 0; i < objc; i++) {
1776 PyObject *s = FromObj(self, objv[i]);
1777 if (!s || PyTuple_SetItem(v, i, s)) {
1778 Py_DECREF(v);
1779 return NULL;
1780 }
1781 }
1782 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001783 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001784 if (PyTuple_Check(arg)) {
1785 Py_INCREF(arg);
1786 return arg;
1787 }
1788
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001789 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1790 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001791
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001792 if (Tcl_SplitList(Tkapp_Interp(self), list,
1793 &argc, &argv) == TCL_ERROR) {
1794 PyMem_Free(list);
1795 return Tkinter_Error(self);
1796 }
Guido van Rossum18468821994-06-20 07:49:28 +00001797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001798 if (!(v = PyTuple_New(argc)))
1799 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001800
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001801 for (i = 0; i < argc; i++) {
1802 PyObject *s = PyUnicode_FromString(argv[i]);
1803 if (!s || PyTuple_SetItem(v, i, s)) {
1804 Py_DECREF(v);
1805 v = NULL;
1806 goto finally;
1807 }
1808 }
Guido van Rossum18468821994-06-20 07:49:28 +00001809
Barry Warsawfa701a81997-01-16 00:15:11 +00001810 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001811 ckfree(FREECAST argv);
1812 PyMem_Free(list);
1813 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001814}
1815
1816static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001817Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001818{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001819 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001820 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001821
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001822 if (!PyArg_ParseTuple(args, "O:split", &arg))
1823 return NULL;
1824 if (PyTclObject_Check(arg)) {
1825 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1826 int objc;
1827 Tcl_Obj **objv;
1828 int i;
1829 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1830 &objc, &objv) == TCL_ERROR) {
1831 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001832 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001833 if (objc == 0)
1834 return PyUnicode_FromString("");
1835 if (objc == 1)
1836 return FromObj(self, objv[0]);
1837 if (!(v = PyTuple_New(objc)))
1838 return NULL;
1839 for (i = 0; i < objc; i++) {
1840 PyObject *s = FromObj(self, objv[i]);
1841 if (!s || PyTuple_SetItem(v, i, s)) {
1842 Py_DECREF(v);
1843 return NULL;
1844 }
1845 }
1846 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001847 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001848 if (PyTuple_Check(arg))
1849 return SplitObj(arg);
1850
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001851 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1852 return NULL;
1853 v = Split(list);
1854 PyMem_Free(list);
1855 return v;
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 +00001860/** Tcl Command **/
1861
Guido van Rossum00d93061998-05-28 23:06:38 +00001862/* Client data struct */
1863typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001864 PyObject *self;
1865 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001866} PythonCmd_ClientData;
1867
1868static int
Fred Drake509d79a2000-07-08 04:04:38 +00001869PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001870{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001871 errorInCmd = 1;
1872 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1873 LEAVE_PYTHON
1874 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001875}
1876
Guido van Rossum18468821994-06-20 07:49:28 +00001877/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001878 * function or method.
1879 */
Guido van Rossum18468821994-06-20 07:49:28 +00001880static int
Fred Drake509d79a2000-07-08 04:04:38 +00001881PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001882{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001883 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001884 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001885 int i, rv;
1886 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001888 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001890 /* TBD: no error checking here since we know, via the
1891 * Tkapp_CreateCommand() that the client data is a two-tuple
1892 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001893 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001894
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001895 /* Create argument list (argv1, ..., argvN) */
1896 if (!(arg = PyTuple_New(argc - 1)))
1897 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001898
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001899 for (i = 0; i < (argc - 1); i++) {
1900 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04001901 if (!s) {
1902 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
1903 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
1904 !strcmp(argv[i + 1], "\xC0\x80")) {
1905 PyErr_Clear();
1906 /* Convert to "strict" utf-8 null */
1907 s = PyUnicode_FromString("\0");
1908 } else {
1909 Py_DECREF(arg);
1910 return PythonCmd_Error(interp);
1911 }
1912 }
1913 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001914 Py_DECREF(arg);
1915 return PythonCmd_Error(interp);
1916 }
1917 }
1918 res = PyEval_CallObject(func, arg);
1919 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001920
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001921 if (res == NULL)
1922 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001923
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001924 obj_res = AsObj(res);
1925 if (obj_res == NULL) {
1926 Py_DECREF(res);
1927 return PythonCmd_Error(interp);
1928 }
1929 else {
1930 Tcl_SetObjResult(interp, obj_res);
1931 rv = TCL_OK;
1932 }
Guido van Rossum2834b972000-10-06 16:58:26 +00001933
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001934 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001935
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001936 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001937
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001938 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001939}
1940
1941static void
Fred Drake509d79a2000-07-08 04:04:38 +00001942PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001943{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001944 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00001945
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001946 ENTER_PYTHON
1947 Py_XDECREF(data->self);
1948 Py_XDECREF(data->func);
1949 PyMem_DEL(data);
1950 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001951}
1952
Barry Warsawfa701a81997-01-16 00:15:11 +00001953
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001954
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001955
Benjamin Peterson5879d412009-03-30 14:51:56 +00001956#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001957TCL_DECLARE_MUTEX(command_mutex)
1958
1959typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001960 Tcl_Event ev;
1961 Tcl_Interp* interp;
1962 char *name;
1963 int create;
1964 int *status;
1965 ClientData *data;
1966 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001967} CommandEvent;
1968
1969static int
1970Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001971{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001972 if (ev->create)
1973 *ev->status = Tcl_CreateCommand(
1974 ev->interp, ev->name, PythonCmd,
1975 ev->data, PythonCmdDelete) == NULL;
1976 else
1977 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1978 Tcl_MutexLock(&command_mutex);
1979 Tcl_ConditionNotify(ev->done);
1980 Tcl_MutexUnlock(&command_mutex);
1981 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001982}
Benjamin Peterson5879d412009-03-30 14:51:56 +00001983#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001984
1985static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001986Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001987{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001988 TkappObject *self = (TkappObject*)selfptr;
1989 PythonCmd_ClientData *data;
1990 char *cmdName;
1991 PyObject *func;
1992 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001993
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001994 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
1995 return NULL;
1996 if (!PyCallable_Check(func)) {
1997 PyErr_SetString(PyExc_TypeError, "command not callable");
1998 return NULL;
1999 }
Guido van Rossum18468821994-06-20 07:49:28 +00002000
Martin v. Löwisa9656492003-03-30 08:44:58 +00002001#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002002 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2003 !WaitForMainloop(self))
2004 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002005#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002006
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002007 data = PyMem_NEW(PythonCmd_ClientData, 1);
2008 if (!data)
2009 return PyErr_NoMemory();
2010 Py_INCREF(self);
2011 Py_INCREF(func);
2012 data->self = selfptr;
2013 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002014#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002015 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2016 Tcl_Condition cond = NULL;
2017 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2018 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2019 ev->interp = self->interp;
2020 ev->create = 1;
2021 ev->name = cmdName;
2022 ev->data = (ClientData)data;
2023 ev->status = &err;
2024 ev->done = &cond;
2025 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2026 Tcl_ConditionFinalize(&cond);
2027 }
2028 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002029#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002030 {
2031 ENTER_TCL
2032 err = Tcl_CreateCommand(
2033 Tkapp_Interp(self), cmdName, PythonCmd,
2034 (ClientData)data, PythonCmdDelete) == NULL;
2035 LEAVE_TCL
2036 }
2037 if (err) {
2038 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2039 PyMem_DEL(data);
2040 return NULL;
2041 }
Guido van Rossum18468821994-06-20 07:49:28 +00002042
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002043 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002044}
2045
Barry Warsawfa701a81997-01-16 00:15:11 +00002046
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002047
Guido van Rossum18468821994-06-20 07:49:28 +00002048static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002049Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002050{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002051 TkappObject *self = (TkappObject*)selfptr;
2052 char *cmdName;
2053 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002054
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002055 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2056 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002057
2058#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002059 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2060 Tcl_Condition cond = NULL;
2061 CommandEvent *ev;
2062 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2063 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2064 ev->interp = self->interp;
2065 ev->create = 0;
2066 ev->name = cmdName;
2067 ev->status = &err;
2068 ev->done = &cond;
2069 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2070 &command_mutex);
2071 Tcl_ConditionFinalize(&cond);
2072 }
2073 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002074#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002075 {
2076 ENTER_TCL
2077 err = Tcl_DeleteCommand(self->interp, cmdName);
2078 LEAVE_TCL
2079 }
2080 if (err == -1) {
2081 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2082 return NULL;
2083 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002084 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002085}
2086
Barry Warsawfa701a81997-01-16 00:15:11 +00002087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002088
Guido van Rossum00d93061998-05-28 23:06:38 +00002089#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002090/** File Handler **/
2091
Guido van Rossum00d93061998-05-28 23:06:38 +00002092typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002093 PyObject *func;
2094 PyObject *file;
2095 int id;
2096 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002097} FileHandler_ClientData;
2098
2099static FileHandler_ClientData *HeadFHCD;
2100
2101static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002102NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002103{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002104 FileHandler_ClientData *p;
2105 p = PyMem_NEW(FileHandler_ClientData, 1);
2106 if (p != NULL) {
2107 Py_XINCREF(func);
2108 Py_XINCREF(file);
2109 p->func = func;
2110 p->file = file;
2111 p->id = id;
2112 p->next = HeadFHCD;
2113 HeadFHCD = p;
2114 }
2115 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002116}
2117
2118static void
Fred Drake509d79a2000-07-08 04:04:38 +00002119DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002120{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002121 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002122
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002123 pp = &HeadFHCD;
2124 while ((p = *pp) != NULL) {
2125 if (p->id == id) {
2126 *pp = p->next;
2127 Py_XDECREF(p->func);
2128 Py_XDECREF(p->file);
2129 PyMem_DEL(p);
2130 }
2131 else
2132 pp = &p->next;
2133 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002134}
2135
Guido van Rossuma597dde1995-01-10 20:56:29 +00002136static void
Fred Drake509d79a2000-07-08 04:04:38 +00002137FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002138{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002139 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2140 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002141
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142 ENTER_PYTHON
2143 func = data->func;
2144 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002145
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002146 arg = Py_BuildValue("(Oi)", file, (long) mask);
2147 res = PyEval_CallObject(func, arg);
2148 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002149
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002150 if (res == NULL) {
2151 errorInCmd = 1;
2152 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2153 }
2154 Py_XDECREF(res);
2155 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002156}
2157
Guido van Rossum18468821994-06-20 07:49:28 +00002158static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002159Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2160 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002161{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002162 FileHandler_ClientData *data;
2163 PyObject *file, *func;
2164 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002165
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002166 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2167 &file, &mask, &func))
2168 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002169
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002170 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002171
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002172 tfile = PyObject_AsFileDescriptor(file);
2173 if (tfile < 0)
2174 return NULL;
2175 if (!PyCallable_Check(func)) {
2176 PyErr_SetString(PyExc_TypeError, "bad argument list");
2177 return NULL;
2178 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002179
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002180 data = NewFHCD(func, file, tfile);
2181 if (data == NULL)
2182 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002183
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002184 /* Ought to check for null Tcl_File object... */
2185 ENTER_TCL
2186 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2187 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002188 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002189}
2190
2191static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002192Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002193{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002194 PyObject *file;
2195 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002196
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2198 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002199
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002200 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002201
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002202 tfile = PyObject_AsFileDescriptor(file);
2203 if (tfile < 0)
2204 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002205
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002206 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002207
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002208 /* Ought to check for null Tcl_File object... */
2209 ENTER_TCL
2210 Tcl_DeleteFileHandler(tfile);
2211 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002212 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002213}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002214#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002215
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002216
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002217/**** Tktt Object (timer token) ****/
2218
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002219static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002220
Guido van Rossum00d93061998-05-28 23:06:38 +00002221typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002222 PyObject_HEAD
2223 Tcl_TimerToken token;
2224 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002225} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002226
2227static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002228Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002229{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002230 TkttObject *v = (TkttObject *)self;
2231 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002232
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002233 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2234 return NULL;
2235 if (v->token != NULL) {
2236 Tcl_DeleteTimerHandler(v->token);
2237 v->token = NULL;
2238 }
2239 if (func != NULL) {
2240 v->func = NULL;
2241 Py_DECREF(func);
2242 Py_DECREF(v); /* See Tktt_New() */
2243 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002244 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002245}
2246
2247static PyMethodDef Tktt_methods[] =
2248{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002249 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2250 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002251};
2252
2253static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002254Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002255{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002256 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002257
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002258 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002259 if (v == NULL)
2260 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002261 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002262
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002263 Py_INCREF(func);
2264 v->token = NULL;
2265 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002266
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002267 /* Extra reference, deleted when called or when handler is deleted */
2268 Py_INCREF(v);
2269 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002270}
2271
2272static void
Fred Drake509d79a2000-07-08 04:04:38 +00002273Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002274{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002275 TkttObject *v = (TkttObject *)self;
2276 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002277 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002278
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002279 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002280
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002281 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002282 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002283}
2284
Guido van Rossum597ac201998-05-12 14:36:19 +00002285static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002286Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002287{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002288 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002289 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2290 v,
2291 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002292}
2293
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002294static PyType_Slot Tktt_Type_slots[] = {
2295 {Py_tp_dealloc, Tktt_Dealloc},
2296 {Py_tp_repr, Tktt_Repr},
2297 {Py_tp_methods, Tktt_methods},
2298 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002299};
2300
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002301static PyType_Spec Tktt_Type_spec = {
2302 "tktimertoken",
2303 sizeof(TkttObject),
2304 0,
2305 Py_TPFLAGS_DEFAULT,
2306 Tktt_Type_slots,
2307};
Barry Warsawfa701a81997-01-16 00:15:11 +00002308
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002309
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002310/** Timer Handler **/
2311
2312static void
Fred Drake509d79a2000-07-08 04:04:38 +00002313TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002314{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002315 TkttObject *v = (TkttObject *)clientData;
2316 PyObject *func = v->func;
2317 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002318
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002319 if (func == NULL)
2320 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002321
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002322 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002323
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002324 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002326 res = PyEval_CallObject(func, NULL);
2327 Py_DECREF(func);
2328 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002330 if (res == NULL) {
2331 errorInCmd = 1;
2332 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2333 }
2334 else
2335 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002336
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002337 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002338}
2339
2340static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002341Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002342{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002343 int milliseconds;
2344 PyObject *func;
2345 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002346
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002347 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2348 &milliseconds, &func))
2349 return NULL;
2350 if (!PyCallable_Check(func)) {
2351 PyErr_SetString(PyExc_TypeError, "bad argument list");
2352 return NULL;
2353 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002354
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002355 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002356
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002357 v = Tktt_New(func);
2358 if (v) {
2359 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2360 (ClientData)v);
2361 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002362
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002363 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002364}
2365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002366
Guido van Rossum18468821994-06-20 07:49:28 +00002367/** Event Loop **/
2368
Guido van Rossum18468821994-06-20 07:49:28 +00002369static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002370Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002371{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002372 int threshold = 0;
2373 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002374#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002375 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002376#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002377
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002378 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2379 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002380
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002381 CHECK_TCL_APPARTMENT;
2382 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002384 quitMainLoop = 0;
2385 while (Tk_GetNumMainWindows() > threshold &&
2386 !quitMainLoop &&
2387 !errorInCmd)
2388 {
2389 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002390
2391#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002392 if (self->threaded) {
2393 /* Allow other Python threads to run. */
2394 ENTER_TCL
2395 result = Tcl_DoOneEvent(0);
2396 LEAVE_TCL
2397 }
2398 else {
2399 Py_BEGIN_ALLOW_THREADS
2400 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2401 tcl_tstate = tstate;
2402 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2403 tcl_tstate = NULL;
2404 if(tcl_lock)PyThread_release_lock(tcl_lock);
2405 if (result == 0)
2406 Sleep(Tkinter_busywaitinterval);
2407 Py_END_ALLOW_THREADS
2408 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002409#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002410 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002411#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002413 if (PyErr_CheckSignals() != 0) {
2414 self->dispatching = 0;
2415 return NULL;
2416 }
2417 if (result < 0)
2418 break;
2419 }
2420 self->dispatching = 0;
2421 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002422
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002423 if (errorInCmd) {
2424 errorInCmd = 0;
2425 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2426 excInCmd = valInCmd = trbInCmd = NULL;
2427 return NULL;
2428 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002429 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002430}
2431
2432static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002433Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002434{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002435 int flags = 0;
2436 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002438 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2439 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002441 ENTER_TCL
2442 rv = Tcl_DoOneEvent(flags);
2443 LEAVE_TCL
2444 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002445}
2446
2447static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002448Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002449{
2450
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002451 if (!PyArg_ParseTuple(args, ":quit"))
2452 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002454 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002455 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002456}
2457
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002458static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002459Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002460{
2461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002462 if (!PyArg_ParseTuple(args, ":interpaddr"))
2463 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002464
Victor Stinnere1040e22013-09-05 00:22:24 +02002465 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002466}
2467
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002468static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002469Tkapp_TkInit(PyObject *self, PyObject *args)
2470{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 Tcl_Interp *interp = Tkapp_Interp(self);
2472 const char * _tk_exists = NULL;
2473 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002474
Guilherme Polob681df42009-02-09 22:33:59 +00002475#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002476 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2477 * first call failed.
2478 * To avoid the deadlock, we just refuse the second call through
2479 * a static variable.
2480 */
2481 if (tk_load_failed) {
2482 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2483 return NULL;
2484 }
Guilherme Polob681df42009-02-09 22:33:59 +00002485#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002487 /* We want to guard against calling Tk_Init() multiple times */
2488 CHECK_TCL_APPARTMENT;
2489 ENTER_TCL
2490 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2491 ENTER_OVERLAP
2492 if (err == TCL_ERROR) {
2493 /* This sets an exception, but we cannot return right
2494 away because we need to exit the overlap first. */
2495 Tkinter_Error(self);
2496 } else {
2497 _tk_exists = Tkapp_Result(self);
2498 }
2499 LEAVE_OVERLAP_TCL
2500 if (err == TCL_ERROR) {
2501 return NULL;
2502 }
2503 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2504 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002505 PyErr_SetString(Tkinter_TclError,
2506 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002507#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002509#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002510 return NULL;
2511 }
2512 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002513 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002514}
Barry Warsawfa701a81997-01-16 00:15:11 +00002515
Martin v. Löwisffad6332002-11-26 09:28:05 +00002516static PyObject *
2517Tkapp_WantObjects(PyObject *self, PyObject *args)
2518{
2519
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002520 int wantobjects = -1;
2521 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2522 return NULL;
2523 if (wantobjects == -1)
2524 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2525 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002526
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002527 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002528}
2529
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002530static PyObject *
2531Tkapp_WillDispatch(PyObject *self, PyObject *args)
2532{
2533
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002534 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002535
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002536 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002537}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002539
Guido van Rossum18468821994-06-20 07:49:28 +00002540/**** Tkapp Method List ****/
2541
2542static PyMethodDef Tkapp_methods[] =
2543{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002544 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2545 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2546 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002547 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002548 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2549 {"record", Tkapp_Record, METH_VARARGS},
2550 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2551 {"setvar", Tkapp_SetVar, METH_VARARGS},
2552 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2553 {"getvar", Tkapp_GetVar, METH_VARARGS},
2554 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2555 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2556 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2557 {"getint", Tkapp_GetInt, METH_VARARGS},
2558 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2559 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2560 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2561 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2562 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2563 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2564 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2565 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002566 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2567 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002568#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002569 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2570 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002571#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002572 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2573 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2574 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2575 {"quit", Tkapp_Quit, METH_VARARGS},
2576 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2577 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2578 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002579};
2580
Barry Warsawfa701a81997-01-16 00:15:11 +00002581
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002582
Guido van Rossum18468821994-06-20 07:49:28 +00002583/**** Tkapp Type Methods ****/
2584
2585static void
Fred Drake509d79a2000-07-08 04:04:38 +00002586Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002587{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002588 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002589 /*CHECK_TCL_APPARTMENT;*/
2590 ENTER_TCL
2591 Tcl_DeleteInterp(Tkapp_Interp(self));
2592 LEAVE_TCL
2593 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002594 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002595 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002596}
2597
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002598static PyType_Slot Tkapp_Type_slots[] = {
2599 {Py_tp_dealloc, Tkapp_Dealloc},
2600 {Py_tp_methods, Tkapp_methods},
2601 {0, 0}
2602};
2603
2604
2605static PyType_Spec Tkapp_Type_spec = {
2606 "tkapp",
2607 sizeof(TkappObject),
2608 0,
2609 Py_TPFLAGS_DEFAULT,
2610 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002611};
2612
Barry Warsawfa701a81997-01-16 00:15:11 +00002613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002614
Guido van Rossum18468821994-06-20 07:49:28 +00002615/**** Tkinter Module ****/
2616
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002617typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002618 PyObject* tuple;
2619 int size; /* current size */
2620 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002621} FlattenContext;
2622
2623static int
2624_bump(FlattenContext* context, int size)
2625{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002626 /* expand tuple to hold (at least) size new items.
2627 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002628
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002629 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002631 if (maxsize < context->size + size)
2632 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002634 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002635
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002636 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002637}
2638
2639static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002640_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002641{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002642 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002643
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002644 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002645
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002646 if (depth > 1000) {
2647 PyErr_SetString(PyExc_ValueError,
2648 "nesting too deep in _flatten");
2649 return 0;
2650 } else if (PyList_Check(item)) {
2651 size = PyList_GET_SIZE(item);
2652 /* preallocate (assume no nesting) */
2653 if (context->size + size > context->maxsize &&
2654 !_bump(context, size))
2655 return 0;
2656 /* copy items to output tuple */
2657 for (i = 0; i < size; i++) {
2658 PyObject *o = PyList_GET_ITEM(item, i);
2659 if (PyList_Check(o) || PyTuple_Check(o)) {
2660 if (!_flatten1(context, o, depth + 1))
2661 return 0;
2662 } else if (o != Py_None) {
2663 if (context->size + 1 > context->maxsize &&
2664 !_bump(context, 1))
2665 return 0;
2666 Py_INCREF(o);
2667 PyTuple_SET_ITEM(context->tuple,
2668 context->size++, o);
2669 }
2670 }
2671 } else if (PyTuple_Check(item)) {
2672 /* same, for tuples */
2673 size = PyTuple_GET_SIZE(item);
2674 if (context->size + size > context->maxsize &&
2675 !_bump(context, size))
2676 return 0;
2677 for (i = 0; i < size; i++) {
2678 PyObject *o = PyTuple_GET_ITEM(item, i);
2679 if (PyList_Check(o) || PyTuple_Check(o)) {
2680 if (!_flatten1(context, o, depth + 1))
2681 return 0;
2682 } else if (o != Py_None) {
2683 if (context->size + 1 > context->maxsize &&
2684 !_bump(context, 1))
2685 return 0;
2686 Py_INCREF(o);
2687 PyTuple_SET_ITEM(context->tuple,
2688 context->size++, o);
2689 }
2690 }
2691 } else {
2692 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2693 return 0;
2694 }
2695 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002696}
2697
2698static PyObject *
2699Tkinter_Flatten(PyObject* self, PyObject* args)
2700{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002701 FlattenContext context;
2702 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002703
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002704 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2705 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002706
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002707 context.maxsize = PySequence_Size(item);
2708 if (context.maxsize < 0)
2709 return NULL;
2710 if (context.maxsize == 0)
2711 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002712
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002713 context.tuple = PyTuple_New(context.maxsize);
2714 if (!context.tuple)
2715 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002717 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002718
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002719 if (!_flatten1(&context, item,0))
2720 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002721
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002722 if (_PyTuple_Resize(&context.tuple, context.size))
2723 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002724
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002725 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002726}
2727
Guido van Rossum18468821994-06-20 07:49:28 +00002728static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002729Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002730{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002731 char *screenName = NULL;
2732 char *baseName = NULL; /* XXX this is not used anymore;
2733 try getting rid of it. */
2734 char *className = NULL;
2735 int interactive = 0;
2736 int wantobjects = 0;
2737 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2738 int sync = 0; /* pass -sync to wish */
2739 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002743 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2744 &screenName, &baseName, &className,
2745 &interactive, &wantobjects, &wantTk,
2746 &sync, &use))
2747 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002749 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002750 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002751 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002752}
2753
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002754static PyObject *
2755Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2756{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002757 int new_val;
2758 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2759 return NULL;
2760 if (new_val < 0) {
2761 PyErr_SetString(PyExc_ValueError,
2762 "busywaitinterval must be >= 0");
2763 return NULL;
2764 }
2765 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002766 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002767}
2768
2769static char setbusywaitinterval_doc[] =
2770"setbusywaitinterval(n) -> None\n\
2771\n\
2772Set the busy-wait interval in milliseconds between successive\n\
2773calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2774It should be set to a divisor of the maximum time between\n\
2775frames in an animation.";
2776
2777static PyObject *
2778Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2779{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002780 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002781}
2782
2783static char getbusywaitinterval_doc[] =
2784"getbusywaitinterval() -> int\n\
2785\n\
2786Return the current busy-wait interval between successive\n\
2787calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2788
Guido van Rossum18468821994-06-20 07:49:28 +00002789static PyMethodDef moduleMethods[] =
2790{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002791 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2792 {"create", Tkinter_Create, METH_VARARGS},
2793 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2794 setbusywaitinterval_doc},
2795 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2796 METH_NOARGS, getbusywaitinterval_doc},
2797 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002798};
2799
Guido van Rossum7bf15641998-05-22 18:28:17 +00002800#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002801
2802static int stdin_ready = 0;
2803
Guido van Rossumad4db171998-06-13 13:56:28 +00002804#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002805static void
Fred Drake509d79a2000-07-08 04:04:38 +00002806MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002807{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002808 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002809}
Guido van Rossumad4db171998-06-13 13:56:28 +00002810#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002811
Martin v. Löwisa9656492003-03-30 08:44:58 +00002812#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002813static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002814#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002815
Guido van Rossum18468821994-06-20 07:49:28 +00002816static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002817EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002818{
Guido van Rossumad4db171998-06-13 13:56:28 +00002819#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002820 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002821#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002822#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002823 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002824#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002825 stdin_ready = 0;
2826 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002827#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002828 tfile = fileno(stdin);
2829 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002830#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002831 while (!errorInCmd && !stdin_ready) {
2832 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002833#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002834 if (_kbhit()) {
2835 stdin_ready = 1;
2836 break;
2837 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002838#endif
2839#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002840 Py_BEGIN_ALLOW_THREADS
2841 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2842 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002844 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002845
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002846 tcl_tstate = NULL;
2847 if(tcl_lock)PyThread_release_lock(tcl_lock);
2848 if (result == 0)
2849 Sleep(Tkinter_busywaitinterval);
2850 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002851#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002852 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002853#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002854
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002855 if (result < 0)
2856 break;
2857 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002858#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002859 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002860#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002861 if (errorInCmd) {
2862 errorInCmd = 0;
2863 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2864 excInCmd = valInCmd = trbInCmd = NULL;
2865 PyErr_Print();
2866 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002867#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002868 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002869#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002870 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002871}
Guido van Rossum18468821994-06-20 07:49:28 +00002872
Guido van Rossum00d93061998-05-28 23:06:38 +00002873#endif
2874
Guido van Rossum7bf15641998-05-22 18:28:17 +00002875static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002876EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002877{
Guido van Rossum00d93061998-05-28 23:06:38 +00002878#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002879 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002880#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002881 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002882#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002883 PyOS_InputHook = EventHook;
2884 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002885#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002886}
2887
2888static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002889DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002890{
Guido van Rossum00d93061998-05-28 23:06:38 +00002891#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002892 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2893 PyOS_InputHook = NULL;
2894 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002895#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002896}
2897
Barry Warsawfa701a81997-01-16 00:15:11 +00002898
Martin v. Löwis1a214512008-06-11 05:26:20 +00002899static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002900 PyModuleDef_HEAD_INIT,
2901 "_tkinter",
2902 NULL,
2903 -1,
2904 moduleMethods,
2905 NULL,
2906 NULL,
2907 NULL,
2908 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002909};
2910
Mark Hammond62b1ab12002-07-23 06:31:15 +00002911PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002912PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002913{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002914 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00002915
Guido van Rossum00d93061998-05-28 23:06:38 +00002916#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002917 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002918 if (tcl_lock == NULL)
2919 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002920#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002921
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002922 m = PyModule_Create(&_tkintermodule);
2923 if (m == NULL)
2924 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002925
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002926 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
2927 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02002928 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002929 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02002930 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002931 Py_INCREF(o);
2932 if (PyModule_AddObject(m, "TclError", o)) {
2933 Py_DECREF(o);
2934 Py_DECREF(m);
2935 return NULL;
2936 }
2937 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002938
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002939 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
2940 Py_DECREF(m);
2941 return NULL;
2942 }
2943 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
2944 Py_DECREF(m);
2945 return NULL;
2946 }
2947 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
2948 Py_DECREF(m);
2949 return NULL;
2950 }
2951 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
2952 Py_DECREF(m);
2953 return NULL;
2954 }
2955 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
2956 Py_DECREF(m);
2957 return NULL;
2958 }
2959 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
2960 Py_DECREF(m);
2961 return NULL;
2962 }
2963 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
2964 Py_DECREF(m);
2965 return NULL;
2966 }
2967 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
2968 Py_DECREF(m);
2969 return NULL;
2970 }
2971 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
2972 Py_DECREF(m);
2973 return NULL;
2974 }
2975 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
2976 Py_DECREF(m);
2977 return NULL;
2978 }
2979 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
2980 Py_DECREF(m);
2981 return NULL;
2982 }
2983
2984 o = PyType_FromSpec(&Tkapp_Type_spec);
2985 if (o == NULL) {
2986 Py_DECREF(m);
2987 return NULL;
2988 }
2989 if (PyModule_AddObject(m, "TkappType", o)) {
2990 Py_DECREF(o);
2991 Py_DECREF(m);
2992 return NULL;
2993 }
2994 Tkapp_Type = o;
2995
2996 o = PyType_FromSpec(&Tktt_Type_spec);
2997 if (o == NULL) {
2998 Py_DECREF(m);
2999 return NULL;
3000 }
3001 if (PyModule_AddObject(m, "TkttType", o)) {
3002 Py_DECREF(o);
3003 Py_DECREF(m);
3004 return NULL;
3005 }
3006 Tktt_Type = o;
3007
3008 o = PyType_FromSpec(&PyTclObject_Type_spec);
3009 if (o == NULL) {
3010 Py_DECREF(m);
3011 return NULL;
3012 }
3013 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3014 Py_DECREF(o);
3015 Py_DECREF(m);
3016 return NULL;
3017 }
3018 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003019
3020#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003021 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3022 * start waking up. Note that Tcl_FindExecutable will do this, this
3023 * code must be above it! The original warning from
3024 * tkMacOSXAppInit.c is copied below.
3025 *
3026 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3027 * Tcl interpreter for now. It probably should work to do this
3028 * in the other order, but for now it doesn't seem to.
3029 *
3030 */
3031 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003032#endif
3033
3034
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003035 /* This helps the dynamic loader; in Unicode aware Tcl versions
3036 it also helps Tcl find its encodings. */
3037 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3038 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003039 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003040 if (cexe)
3041 Tcl_FindExecutable(PyBytes_AsString(cexe));
3042 Py_XDECREF(cexe);
3043 Py_DECREF(uexe);
3044 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003045
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003046 if (PyErr_Occurred()) {
3047 Py_DECREF(m);
3048 return NULL;
3049 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003050
Guido van Rossum43ff8681998-07-14 18:02:13 +00003051#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003052 /* This was not a good idea; through <Destroy> bindings,
3053 Tcl_Finalize() may invoke Python code but at that point the
3054 interpreter and thread state have already been destroyed! */
3055 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003056#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003057 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003058}