blob: e022a7a7e1564ef50a77e6e4b9bae1fbd1440f66 [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{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300740 PyObject *repr, *str = PyTclObject_str(self, NULL);
741 if (str == NULL)
742 return NULL;
743 repr = PyUnicode_FromFormat("<%s object: %R>",
744 self->value->typePtr->name, str);
745 Py_DECREF(str);
746 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000747}
748
Mark Dickinson211c6252009-02-01 10:28:51 +0000749#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
750
751static PyObject *
752PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000753{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 int result;
755 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000756
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000757 /* neither argument should be NULL, unless something's gone wrong */
758 if (self == NULL || other == NULL) {
759 PyErr_BadInternalCall();
760 return NULL;
761 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000762
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000763 /* both arguments should be instances of PyTclObject */
764 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
765 v = Py_NotImplemented;
766 goto finished;
767 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 if (self == other)
770 /* fast path when self and other are identical */
771 result = 0;
772 else
773 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
774 Tcl_GetString(((PyTclObject *)other)->value));
775 /* Convert return value to a Boolean */
776 switch (op) {
777 case Py_EQ:
778 v = TEST_COND(result == 0);
779 break;
780 case Py_NE:
781 v = TEST_COND(result != 0);
782 break;
783 case Py_LE:
784 v = TEST_COND(result <= 0);
785 break;
786 case Py_GE:
787 v = TEST_COND(result >= 0);
788 break;
789 case Py_LT:
790 v = TEST_COND(result < 0);
791 break;
792 case Py_GT:
793 v = TEST_COND(result > 0);
794 break;
795 default:
796 PyErr_BadArgument();
797 return NULL;
798 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000799 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000800 Py_INCREF(v);
801 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000802}
803
Martin v. Löwis39195712003-01-04 00:33:13 +0000804PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
805
Martin v. Löwisffad6332002-11-26 09:28:05 +0000806static PyObject*
807get_typename(PyTclObject* obj, void* ignored)
808{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000809 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000810}
811
Martin v. Löwis39195712003-01-04 00:33:13 +0000812
Martin v. Löwisffad6332002-11-26 09:28:05 +0000813static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000814 {"typename", (getter)get_typename, NULL, get_typename__doc__},
815 {"string", (getter)PyTclObject_string, NULL,
816 PyTclObject_string__doc__},
817 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000818};
819
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300820static PyType_Slot PyTclObject_Type_slots[] = {
821 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
822 {Py_tp_repr, (reprfunc)PyTclObject_repr},
823 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200824 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300825 {Py_tp_richcompare, PyTclObject_richcompare},
826 {Py_tp_getset, PyTclObject_getsetlist},
827 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000828};
829
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300830static PyType_Spec PyTclObject_Type_spec = {
831 "_tkinter.Tcl_Obj",
832 sizeof(PyTclObject),
833 0,
834 Py_TPFLAGS_DEFAULT,
835 PyTclObject_Type_slots,
836};
837
838
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000839static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000840AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000841{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000842 Tcl_Obj *result;
843 long longVal;
844 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000845
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000846 if (PyBytes_Check(value))
847 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
848 PyBytes_GET_SIZE(value));
849 else if (PyBool_Check(value))
850 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
851 else if (PyLong_CheckExact(value) &&
852 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
853 !overflow)) {
854 /* If there is an overflow in the long conversion,
855 fall through to default object handling. */
856 return Tcl_NewLongObj(longVal);
857 }
858 else if (PyFloat_Check(value))
859 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
860 else if (PyTuple_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300861 Tcl_Obj **argv;
862 Py_ssize_t size, i;
863
864 size = PyTuple_Size(value);
865 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
866 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
867 return NULL;
868 }
869 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000870 if(!argv)
871 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300872 for (i = 0; i < size; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000873 argv[i] = AsObj(PyTuple_GetItem(value,i));
874 result = Tcl_NewListObj(PyTuple_Size(value), argv);
875 ckfree(FREECAST argv);
876 return result;
877 }
878 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200879 void *inbuf;
880 Py_ssize_t size;
881 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000882 Tcl_UniChar *outbuf = NULL;
883 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200884 size_t allocsize;
885
886 if (PyUnicode_READY(value) == -1)
887 return NULL;
888
889 inbuf = PyUnicode_DATA(value);
890 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300891 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
892 PyErr_SetString(PyExc_OverflowError, "string is too long");
893 return NULL;
894 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200895 kind = PyUnicode_KIND(value);
896 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
897 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000898 /* Else overflow occurred, and we take the next exit */
899 if (!outbuf) {
900 PyErr_NoMemory();
901 return NULL;
902 }
903 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200904 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
905 /* We cannot test for sizeof(Tcl_UniChar) directly,
906 so we test for UTF-8 size instead. */
907#if TCL_UTF_MAX == 3
908 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000909 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200910 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100911 "character U+%x is above the range "
912 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100913 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000914 ckfree(FREECAST outbuf);
915 return NULL;
916 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300917#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200918 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000919 }
920 result = Tcl_NewUnicodeObj(outbuf, size);
921 ckfree(FREECAST outbuf);
922 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000923 }
924 else if(PyTclObject_Check(value)) {
925 Tcl_Obj *v = ((PyTclObject*)value)->value;
926 Tcl_IncrRefCount(v);
927 return v;
928 }
929 else {
930 PyObject *v = PyObject_Str(value);
931 if (!v)
932 return 0;
933 result = AsObj(v);
934 Py_DECREF(v);
935 return result;
936 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000937}
938
Martin v. Löwisffad6332002-11-26 09:28:05 +0000939static PyObject*
940FromObj(PyObject* tkapp, Tcl_Obj *value)
941{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000942 PyObject *result = NULL;
943 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000944
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000945 if (value->typePtr == NULL) {
946 return PyUnicode_FromStringAndSize(value->bytes,
947 value->length);
948 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000949
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000950 if (value->typePtr == app->BooleanType) {
951 result = value->internalRep.longValue ? Py_True : Py_False;
952 Py_INCREF(result);
953 return result;
954 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000955
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000956 if (value->typePtr == app->ByteArrayType) {
957 int size;
958 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
959 return PyBytes_FromStringAndSize(data, size);
960 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000961
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000962 if (value->typePtr == app->DoubleType) {
963 return PyFloat_FromDouble(value->internalRep.doubleValue);
964 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000965
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000966 if (value->typePtr == app->IntType) {
967 return PyLong_FromLong(value->internalRep.longValue);
968 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000969
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000970 if (value->typePtr == app->ListType) {
971 int size;
972 int i, status;
973 PyObject *elem;
974 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000975
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000976 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
977 if (status == TCL_ERROR)
978 return Tkinter_Error(tkapp);
979 result = PyTuple_New(size);
980 if (!result)
981 return NULL;
982 for (i = 0; i < size; i++) {
983 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
984 value, i, &tcl_elem);
985 if (status == TCL_ERROR) {
986 Py_DECREF(result);
987 return Tkinter_Error(tkapp);
988 }
989 elem = FromObj(tkapp, tcl_elem);
990 if (!elem) {
991 Py_DECREF(result);
992 return NULL;
993 }
994 PyTuple_SetItem(result, i, elem);
995 }
996 return result;
997 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000998
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000999 if (value->typePtr == app->ProcBodyType) {
1000 /* fall through: return tcl object. */
1001 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001002
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001003 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001004#if TCL_UTF_MAX==3
1005 return PyUnicode_FromKindAndData(
1006 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
1007 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001008#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001009 return PyUnicode_FromKindAndData(
1010 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
1011 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001012#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001013 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001014
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001015 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001016}
1017
Benjamin Peterson5879d412009-03-30 14:51:56 +00001018#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001019/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001020TCL_DECLARE_MUTEX(call_mutex)
1021
1022typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001023 Tcl_Event ev; /* Must be first */
1024 TkappObject *self;
1025 PyObject *args;
1026 int flags;
1027 PyObject **res;
1028 PyObject **exc_type, **exc_value, **exc_tb;
1029 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001030} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001031#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001032
1033void
1034Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001035{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001036 int i;
1037 for (i = 0; i < objc; i++)
1038 Tcl_DecrRefCount(objv[i]);
1039 if (objv != objStore)
1040 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001041}
Guido van Rossum18468821994-06-20 07:49:28 +00001042
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001043/* Convert Python objects to Tcl objects. This must happen in the
1044 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001045
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001046static Tcl_Obj**
1047Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1048{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001049 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001050 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001051 if (args == NULL)
1052 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001053
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001054 else if (!PyTuple_Check(args)) {
1055 objv[0] = AsObj(args);
1056 if (objv[0] == 0)
1057 goto finally;
1058 objc = 1;
1059 Tcl_IncrRefCount(objv[0]);
1060 }
1061 else {
1062 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001063
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001064 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001065 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1066 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1067 return NULL;
1068 }
1069 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001070 if (objv == NULL) {
1071 PyErr_NoMemory();
1072 objc = 0;
1073 goto finally;
1074 }
1075 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001076
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001077 for (i = 0; i < objc; i++) {
1078 PyObject *v = PyTuple_GetItem(args, i);
1079 if (v == Py_None) {
1080 objc = i;
1081 break;
1082 }
1083 objv[i] = AsObj(v);
1084 if (!objv[i]) {
1085 /* Reset objc, so it attempts to clear
1086 objects only up to i. */
1087 objc = i;
1088 goto finally;
1089 }
1090 Tcl_IncrRefCount(objv[i]);
1091 }
1092 }
1093 *pobjc = objc;
1094 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001095finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001096 Tkapp_CallDeallocArgs(objv, objStore, objc);
1097 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001098}
Guido van Rossum212643f1998-04-29 16:22:14 +00001099
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001100/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001101
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001102static PyObject*
1103Tkapp_CallResult(TkappObject *self)
1104{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 PyObject *res = NULL;
1106 if(self->wantobjects) {
1107 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1108 /* Not sure whether the IncrRef is necessary, but something
1109 may overwrite the interpreter result while we are
1110 converting it. */
1111 Tcl_IncrRefCount(value);
1112 res = FromObj((PyObject*)self, value);
1113 Tcl_DecrRefCount(value);
1114 } else {
Serhiy Storchaka31f477c2013-09-20 23:21:44 +03001115 res = PyUnicode_FromString(Tcl_GetStringResult(self->interp));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001116 }
1117 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001118}
Guido van Rossum632de272000-03-29 00:19:50 +00001119
Benjamin Peterson5879d412009-03-30 14:51:56 +00001120#ifdef WITH_THREAD
1121
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001122/* Tkapp_CallProc is the event procedure that is executed in the context of
1123 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1124 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001125
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001126static int
1127Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1128{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001129 Tcl_Obj *objStore[ARGSZ];
1130 Tcl_Obj **objv;
1131 int objc;
1132 int i;
1133 ENTER_PYTHON
1134 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1135 if (!objv) {
1136 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1137 *(e->res) = NULL;
1138 }
1139 LEAVE_PYTHON
1140 if (!objv)
1141 goto done;
1142 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1143 ENTER_PYTHON
1144 if (i == TCL_ERROR) {
1145 *(e->res) = NULL;
1146 *(e->exc_type) = NULL;
1147 *(e->exc_tb) = NULL;
1148 *(e->exc_value) = PyObject_CallFunction(
1149 Tkinter_TclError, "s",
1150 Tcl_GetStringResult(e->self->interp));
1151 }
1152 else {
1153 *(e->res) = Tkapp_CallResult(e->self);
1154 }
1155 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001156
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001157 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001158done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001159 /* Wake up calling thread. */
1160 Tcl_MutexLock(&call_mutex);
1161 Tcl_ConditionNotify(e->done);
1162 Tcl_MutexUnlock(&call_mutex);
1163 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001164}
1165
Benjamin Peterson5879d412009-03-30 14:51:56 +00001166#endif
1167
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001168/* This is the main entry point for calling a Tcl command.
1169 It supports three cases, with regard to threading:
1170 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1171 the context of the calling thread.
1172 2. Tcl is threaded, caller of the command is in the interpreter thread:
1173 Execute the command in the calling thread. Since the Tcl lock will
1174 not be used, we can merge that with case 1.
1175 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1176 the interpreter thread. Allocation of Tcl objects needs to occur in the
1177 interpreter thread, so we ship the PyObject* args to the target thread,
1178 and perform processing there. */
1179
1180static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001181Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001182{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001183 Tcl_Obj *objStore[ARGSZ];
1184 Tcl_Obj **objv = NULL;
1185 int objc, i;
1186 PyObject *res = NULL;
1187 TkappObject *self = (TkappObject*)selfptr;
1188 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001189
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001190 /* If args is a single tuple, replace with contents of tuple */
1191 if (1 == PyTuple_Size(args)){
1192 PyObject* item = PyTuple_GetItem(args, 0);
1193 if (PyTuple_Check(item))
1194 args = item;
1195 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001196#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001197 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1198 /* We cannot call the command directly. Instead, we must
1199 marshal the parameters to the interpreter thread. */
1200 Tkapp_CallEvent *ev;
1201 Tcl_Condition cond = NULL;
1202 PyObject *exc_type, *exc_value, *exc_tb;
1203 if (!WaitForMainloop(self))
1204 return NULL;
1205 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1206 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1207 ev->self = self;
1208 ev->args = args;
1209 ev->res = &res;
1210 ev->exc_type = &exc_type;
1211 ev->exc_value = &exc_value;
1212 ev->exc_tb = &exc_tb;
1213 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001214
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001215 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001216
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001217 if (res == NULL) {
1218 if (exc_type)
1219 PyErr_Restore(exc_type, exc_value, exc_tb);
1220 else
1221 PyErr_SetObject(Tkinter_TclError, exc_value);
1222 }
1223 Tcl_ConditionFinalize(&cond);
1224 }
1225 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001226#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001227 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001228
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001229 objv = Tkapp_CallArgs(args, objStore, &objc);
1230 if (!objv)
1231 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001232
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001233 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001234
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001235 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001236
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001237 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001239 if (i == TCL_ERROR)
1240 Tkinter_Error(selfptr);
1241 else
1242 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001243
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001244 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001245
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001246 Tkapp_CallDeallocArgs(objv, objStore, objc);
1247 }
1248 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001249}
1250
1251
1252static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001253Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001254{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001255 char *script;
1256 PyObject *res = NULL;
1257 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001258
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001259 if (!PyArg_ParseTuple(args, "s:eval", &script))
1260 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001262 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001263
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001264 ENTER_TCL
1265 err = Tcl_Eval(Tkapp_Interp(self), script);
1266 ENTER_OVERLAP
1267 if (err == TCL_ERROR)
1268 res = Tkinter_Error(self);
1269 else
1270 res = PyUnicode_FromString(Tkapp_Result(self));
1271 LEAVE_OVERLAP_TCL
1272 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001273}
1274
1275static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001276Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001277{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001278 char *fileName;
1279 PyObject *res = NULL;
1280 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001282 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1283 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001284
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001285 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001287 ENTER_TCL
1288 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1289 ENTER_OVERLAP
1290 if (err == TCL_ERROR)
1291 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001292
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001293 else
1294 res = PyUnicode_FromString(Tkapp_Result(self));
1295 LEAVE_OVERLAP_TCL
1296 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001297}
1298
1299static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001300Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001301{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001302 char *script;
1303 PyObject *res = NULL;
1304 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001305
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001306 if (!PyArg_ParseTuple(args, "s", &script))
1307 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001308
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001309 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001310
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001311 ENTER_TCL
1312 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1313 ENTER_OVERLAP
1314 if (err == TCL_ERROR)
1315 res = Tkinter_Error(self);
1316 else
1317 res = PyUnicode_FromString(Tkapp_Result(self));
1318 LEAVE_OVERLAP_TCL
1319 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001320}
1321
1322static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001323Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001324{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001326
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001327 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1328 return NULL;
1329 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001330
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001331 ENTER_TCL
1332 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1333 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001334
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001335 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001336}
1337
Barry Warsawfa701a81997-01-16 00:15:11 +00001338
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001339
Guido van Rossum18468821994-06-20 07:49:28 +00001340/** Tcl Variable **/
1341
Benjamin Peterson5879d412009-03-30 14:51:56 +00001342typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1343
1344#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001345TCL_DECLARE_MUTEX(var_mutex)
1346
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001347typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001348 Tcl_Event ev; /* must be first */
1349 PyObject *self;
1350 PyObject *args;
1351 int flags;
1352 EventFunc func;
1353 PyObject **res;
1354 PyObject **exc_type;
1355 PyObject **exc_val;
1356 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001357} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001358#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001359
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001360static int
1361varname_converter(PyObject *in, void *_out)
1362{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001363 char **out = (char**)_out;
1364 if (PyBytes_Check(in)) {
1365 *out = PyBytes_AsString(in);
1366 return 1;
1367 }
1368 if (PyUnicode_Check(in)) {
1369 *out = _PyUnicode_AsString(in);
1370 return 1;
1371 }
1372 if (PyTclObject_Check(in)) {
1373 *out = PyTclObject_TclString(in);
1374 return 1;
1375 }
1376 /* XXX: Should give diagnostics. */
1377 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001378}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001379
Benjamin Peterson5879d412009-03-30 14:51:56 +00001380#ifdef WITH_THREAD
1381
Martin v. Löwis59683e82008-06-13 07:50:45 +00001382static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001383var_perform(VarEvent *ev)
1384{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001385 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1386 if (!*(ev->res)) {
1387 PyObject *exc, *val, *tb;
1388 PyErr_Fetch(&exc, &val, &tb);
1389 PyErr_NormalizeException(&exc, &val, &tb);
1390 *(ev->exc_type) = exc;
1391 *(ev->exc_val) = val;
1392 Py_DECREF(tb);
1393 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001394
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001395}
1396
1397static int
1398var_proc(VarEvent* ev, int flags)
1399{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001400 ENTER_PYTHON
1401 var_perform(ev);
1402 Tcl_MutexLock(&var_mutex);
1403 Tcl_ConditionNotify(ev->cond);
1404 Tcl_MutexUnlock(&var_mutex);
1405 LEAVE_PYTHON
1406 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001407}
1408
Benjamin Peterson5879d412009-03-30 14:51:56 +00001409#endif
1410
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001411static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001412var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001413{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001414#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001415 TkappObject *self = (TkappObject*)selfptr;
1416 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1417 TkappObject *self = (TkappObject*)selfptr;
1418 VarEvent *ev;
1419 PyObject *res, *exc_type, *exc_val;
1420 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001421
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001422 /* The current thread is not the interpreter thread. Marshal
1423 the call to the interpreter thread, then wait for
1424 completion. */
1425 if (!WaitForMainloop(self))
1426 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001427
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001428 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001429
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001430 ev->self = selfptr;
1431 ev->args = args;
1432 ev->flags = flags;
1433 ev->func = func;
1434 ev->res = &res;
1435 ev->exc_type = &exc_type;
1436 ev->exc_val = &exc_val;
1437 ev->cond = &cond;
1438 ev->ev.proc = (Tcl_EventProc*)var_proc;
1439 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1440 Tcl_ConditionFinalize(&cond);
1441 if (!res) {
1442 PyErr_SetObject(exc_type, exc_val);
1443 Py_DECREF(exc_type);
1444 Py_DECREF(exc_val);
1445 return NULL;
1446 }
1447 return res;
1448 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001449#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001450 /* Tcl is not threaded, or this is the interpreter thread. */
1451 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001452}
1453
Guido van Rossum18468821994-06-20 07:49:28 +00001454static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001455SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001456{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001457 char *name1, *name2;
1458 PyObject *newValue;
1459 PyObject *res = NULL;
1460 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001462 if (PyArg_ParseTuple(args, "O&O:setvar",
1463 varname_converter, &name1, &newValue)) {
1464 /* XXX Acquire tcl lock??? */
1465 newval = AsObj(newValue);
1466 if (newval == NULL)
1467 return NULL;
1468 ENTER_TCL
1469 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1470 newval, flags);
1471 ENTER_OVERLAP
1472 if (!ok)
1473 Tkinter_Error(self);
1474 else {
1475 res = Py_None;
1476 Py_INCREF(res);
1477 }
1478 LEAVE_OVERLAP_TCL
1479 }
1480 else {
1481 PyErr_Clear();
1482 if (PyArg_ParseTuple(args, "ssO:setvar",
1483 &name1, &name2, &newValue)) {
1484 /* XXX must hold tcl lock already??? */
1485 newval = AsObj(newValue);
1486 ENTER_TCL
1487 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1488 ENTER_OVERLAP
1489 if (!ok)
1490 Tkinter_Error(self);
1491 else {
1492 res = Py_None;
1493 Py_INCREF(res);
1494 }
1495 LEAVE_OVERLAP_TCL
1496 }
1497 else {
1498 return NULL;
1499 }
1500 }
1501 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001502}
1503
1504static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001505Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001506{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001507 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001508}
1509
1510static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001511Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001512{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001513 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001514}
1515
Barry Warsawfa701a81997-01-16 00:15:11 +00001516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001517
Guido van Rossum18468821994-06-20 07:49:28 +00001518static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001519GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001520{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001521 char *name1, *name2=NULL;
1522 PyObject *res = NULL;
1523 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001524
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001525 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1526 varname_converter, &name1, &name2))
1527 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001529 ENTER_TCL
1530 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1531 ENTER_OVERLAP
1532 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001533 PyErr_SetString(Tkinter_TclError,
1534 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001535 } else {
1536 if (((TkappObject*)self)->wantobjects) {
1537 res = FromObj(self, tres);
1538 }
1539 else {
1540 res = PyUnicode_FromString(Tcl_GetString(tres));
1541 }
1542 }
1543 LEAVE_OVERLAP_TCL
1544 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001545}
1546
1547static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001548Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001549{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001551}
1552
1553static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001554Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001555{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001556 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001557}
1558
Barry Warsawfa701a81997-01-16 00:15:11 +00001559
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001560
Guido van Rossum18468821994-06-20 07:49:28 +00001561static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001562UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001563{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001564 char *name1, *name2=NULL;
1565 int code;
1566 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001567
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1569 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001571 ENTER_TCL
1572 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1573 ENTER_OVERLAP
1574 if (code == TCL_ERROR)
1575 res = Tkinter_Error(self);
1576 else {
1577 Py_INCREF(Py_None);
1578 res = Py_None;
1579 }
1580 LEAVE_OVERLAP_TCL
1581 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001582}
1583
1584static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001585Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001586{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001587 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001588}
1589
1590static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001591Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001592{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001593 return var_invoke(UnsetVar, self, args,
1594 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001595}
1596
Barry Warsawfa701a81997-01-16 00:15:11 +00001597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001598
Guido van Rossum18468821994-06-20 07:49:28 +00001599/** Tcl to Python **/
1600
1601static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001602Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001603{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001604 char *s;
1605 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001607 if (PyTuple_Size(args) == 1) {
1608 PyObject* o = PyTuple_GetItem(args, 0);
1609 if (PyLong_Check(o)) {
1610 Py_INCREF(o);
1611 return o;
1612 }
1613 }
1614 if (!PyArg_ParseTuple(args, "s:getint", &s))
1615 return NULL;
1616 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1617 return Tkinter_Error(self);
1618 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001619}
1620
1621static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001622Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001623{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001624 char *s;
1625 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001626
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001627 if (PyTuple_Size(args) == 1) {
1628 PyObject *o = PyTuple_GetItem(args, 0);
1629 if (PyFloat_Check(o)) {
1630 Py_INCREF(o);
1631 return o;
1632 }
1633 }
1634 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1635 return NULL;
1636 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1637 return Tkinter_Error(self);
1638 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001639}
1640
1641static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001642Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001643{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001644 char *s;
1645 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001647 if (PyTuple_Size(args) == 1) {
1648 PyObject *o = PyTuple_GetItem(args, 0);
1649 if (PyLong_Check(o)) {
1650 Py_INCREF(o);
1651 return o;
1652 }
1653 }
1654 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1655 return NULL;
1656 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1657 return Tkinter_Error(self);
1658 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001659}
1660
1661static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001662Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001663{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001664 char *s;
1665 PyObject *res = NULL;
1666 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001668 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1669 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001670
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001671 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001673 ENTER_TCL
1674 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1675 ENTER_OVERLAP
1676 if (retval == TCL_ERROR)
1677 res = Tkinter_Error(self);
1678 else
1679 res = Py_BuildValue("s", Tkapp_Result(self));
1680 LEAVE_OVERLAP_TCL
1681 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001682}
1683
1684static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001685Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001686{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001687 char *s;
1688 PyObject *res = NULL;
1689 int retval;
1690 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001691
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001692 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1693 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001695 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001696
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001697 ENTER_TCL
1698 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1699 ENTER_OVERLAP
1700 if (retval == TCL_ERROR)
1701 res = Tkinter_Error(self);
1702 else
1703 res = Py_BuildValue("l", v);
1704 LEAVE_OVERLAP_TCL
1705 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001706}
1707
1708static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001709Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001710{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001711 char *s;
1712 PyObject *res = NULL;
1713 double v;
1714 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001715
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001716 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1717 return NULL;
1718 CHECK_TCL_APPARTMENT;
1719 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1720 ENTER_TCL
1721 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1722 ENTER_OVERLAP
1723 PyFPE_END_PROTECT(retval)
1724 if (retval == TCL_ERROR)
1725 res = Tkinter_Error(self);
1726 else
1727 res = Py_BuildValue("d", v);
1728 LEAVE_OVERLAP_TCL
1729 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001730}
1731
1732static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001733Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001734{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001735 char *s;
1736 PyObject *res = NULL;
1737 int retval;
1738 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001739
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001740 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1741 return NULL;
1742 CHECK_TCL_APPARTMENT;
1743 ENTER_TCL
1744 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1745 ENTER_OVERLAP
1746 if (retval == TCL_ERROR)
1747 res = Tkinter_Error(self);
1748 else
1749 res = Py_BuildValue("i", v);
1750 LEAVE_OVERLAP_TCL
1751 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001752}
1753
Barry Warsawfa701a81997-01-16 00:15:11 +00001754
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001755
Guido van Rossum18468821994-06-20 07:49:28 +00001756static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001757Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001758{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001759 char *list;
1760 int argc;
1761 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001762 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001763 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001764
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001765 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1766 return NULL;
1767 if (PyTclObject_Check(arg)) {
1768 int objc;
1769 Tcl_Obj **objv;
1770 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1771 ((PyTclObject*)arg)->value,
1772 &objc, &objv) == TCL_ERROR) {
1773 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001774 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001775 if (!(v = PyTuple_New(objc)))
1776 return NULL;
1777 for (i = 0; i < objc; i++) {
1778 PyObject *s = FromObj(self, objv[i]);
1779 if (!s || PyTuple_SetItem(v, i, s)) {
1780 Py_DECREF(v);
1781 return NULL;
1782 }
1783 }
1784 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001785 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001786 if (PyTuple_Check(arg)) {
1787 Py_INCREF(arg);
1788 return arg;
1789 }
1790
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001791 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1792 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001793
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001794 if (Tcl_SplitList(Tkapp_Interp(self), list,
1795 &argc, &argv) == TCL_ERROR) {
1796 PyMem_Free(list);
1797 return Tkinter_Error(self);
1798 }
Guido van Rossum18468821994-06-20 07:49:28 +00001799
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001800 if (!(v = PyTuple_New(argc)))
1801 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001802
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001803 for (i = 0; i < argc; i++) {
1804 PyObject *s = PyUnicode_FromString(argv[i]);
1805 if (!s || PyTuple_SetItem(v, i, s)) {
1806 Py_DECREF(v);
1807 v = NULL;
1808 goto finally;
1809 }
1810 }
Guido van Rossum18468821994-06-20 07:49:28 +00001811
Barry Warsawfa701a81997-01-16 00:15:11 +00001812 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001813 ckfree(FREECAST argv);
1814 PyMem_Free(list);
1815 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001816}
1817
1818static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001819Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001820{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001821 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001822 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001823
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001824 if (!PyArg_ParseTuple(args, "O:split", &arg))
1825 return NULL;
1826 if (PyTclObject_Check(arg)) {
1827 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1828 int objc;
1829 Tcl_Obj **objv;
1830 int i;
1831 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1832 &objc, &objv) == TCL_ERROR) {
1833 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001834 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001835 if (objc == 0)
1836 return PyUnicode_FromString("");
1837 if (objc == 1)
1838 return FromObj(self, objv[0]);
1839 if (!(v = PyTuple_New(objc)))
1840 return NULL;
1841 for (i = 0; i < objc; i++) {
1842 PyObject *s = FromObj(self, objv[i]);
1843 if (!s || PyTuple_SetItem(v, i, s)) {
1844 Py_DECREF(v);
1845 return NULL;
1846 }
1847 }
1848 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001849 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001850 if (PyTuple_Check(arg))
1851 return SplitObj(arg);
1852
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001853 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1854 return NULL;
1855 v = Split(list);
1856 PyMem_Free(list);
1857 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001858}
1859
Barry Warsawfa701a81997-01-16 00:15:11 +00001860
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001861
Guido van Rossum18468821994-06-20 07:49:28 +00001862/** Tcl Command **/
1863
Guido van Rossum00d93061998-05-28 23:06:38 +00001864/* Client data struct */
1865typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001866 PyObject *self;
1867 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001868} PythonCmd_ClientData;
1869
1870static int
Fred Drake509d79a2000-07-08 04:04:38 +00001871PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001872{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001873 errorInCmd = 1;
1874 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1875 LEAVE_PYTHON
1876 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001877}
1878
Guido van Rossum18468821994-06-20 07:49:28 +00001879/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001880 * function or method.
1881 */
Guido van Rossum18468821994-06-20 07:49:28 +00001882static int
Fred Drake509d79a2000-07-08 04:04:38 +00001883PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001884{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001885 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001886 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001887 int i, rv;
1888 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001890 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001891
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001892 /* TBD: no error checking here since we know, via the
1893 * Tkapp_CreateCommand() that the client data is a two-tuple
1894 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001895 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001896
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001897 /* Create argument list (argv1, ..., argvN) */
1898 if (!(arg = PyTuple_New(argc - 1)))
1899 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001900
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001901 for (i = 0; i < (argc - 1); i++) {
1902 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04001903 if (!s) {
1904 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
1905 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
1906 !strcmp(argv[i + 1], "\xC0\x80")) {
1907 PyErr_Clear();
1908 /* Convert to "strict" utf-8 null */
1909 s = PyUnicode_FromString("\0");
1910 } else {
1911 Py_DECREF(arg);
1912 return PythonCmd_Error(interp);
1913 }
1914 }
1915 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001916 Py_DECREF(arg);
1917 return PythonCmd_Error(interp);
1918 }
1919 }
1920 res = PyEval_CallObject(func, arg);
1921 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001922
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001923 if (res == NULL)
1924 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001925
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001926 obj_res = AsObj(res);
1927 if (obj_res == NULL) {
1928 Py_DECREF(res);
1929 return PythonCmd_Error(interp);
1930 }
1931 else {
1932 Tcl_SetObjResult(interp, obj_res);
1933 rv = TCL_OK;
1934 }
Guido van Rossum2834b972000-10-06 16:58:26 +00001935
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001936 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001937
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001938 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001939
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001940 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001941}
1942
1943static void
Fred Drake509d79a2000-07-08 04:04:38 +00001944PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001945{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001946 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00001947
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001948 ENTER_PYTHON
1949 Py_XDECREF(data->self);
1950 Py_XDECREF(data->func);
1951 PyMem_DEL(data);
1952 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001953}
1954
Barry Warsawfa701a81997-01-16 00:15:11 +00001955
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001956
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001957
Benjamin Peterson5879d412009-03-30 14:51:56 +00001958#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001959TCL_DECLARE_MUTEX(command_mutex)
1960
1961typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001962 Tcl_Event ev;
1963 Tcl_Interp* interp;
1964 char *name;
1965 int create;
1966 int *status;
1967 ClientData *data;
1968 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001969} CommandEvent;
1970
1971static int
1972Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001973{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001974 if (ev->create)
1975 *ev->status = Tcl_CreateCommand(
1976 ev->interp, ev->name, PythonCmd,
1977 ev->data, PythonCmdDelete) == NULL;
1978 else
1979 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1980 Tcl_MutexLock(&command_mutex);
1981 Tcl_ConditionNotify(ev->done);
1982 Tcl_MutexUnlock(&command_mutex);
1983 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001984}
Benjamin Peterson5879d412009-03-30 14:51:56 +00001985#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001986
1987static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001988Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001989{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001990 TkappObject *self = (TkappObject*)selfptr;
1991 PythonCmd_ClientData *data;
1992 char *cmdName;
1993 PyObject *func;
1994 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001995
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001996 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
1997 return NULL;
1998 if (!PyCallable_Check(func)) {
1999 PyErr_SetString(PyExc_TypeError, "command not callable");
2000 return NULL;
2001 }
Guido van Rossum18468821994-06-20 07:49:28 +00002002
Martin v. Löwisa9656492003-03-30 08:44:58 +00002003#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002004 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2005 !WaitForMainloop(self))
2006 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002007#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002008
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002009 data = PyMem_NEW(PythonCmd_ClientData, 1);
2010 if (!data)
2011 return PyErr_NoMemory();
2012 Py_INCREF(self);
2013 Py_INCREF(func);
2014 data->self = selfptr;
2015 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002016#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002017 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2018 Tcl_Condition cond = NULL;
2019 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2020 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2021 ev->interp = self->interp;
2022 ev->create = 1;
2023 ev->name = cmdName;
2024 ev->data = (ClientData)data;
2025 ev->status = &err;
2026 ev->done = &cond;
2027 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2028 Tcl_ConditionFinalize(&cond);
2029 }
2030 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002031#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002032 {
2033 ENTER_TCL
2034 err = Tcl_CreateCommand(
2035 Tkapp_Interp(self), cmdName, PythonCmd,
2036 (ClientData)data, PythonCmdDelete) == NULL;
2037 LEAVE_TCL
2038 }
2039 if (err) {
2040 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2041 PyMem_DEL(data);
2042 return NULL;
2043 }
Guido van Rossum18468821994-06-20 07:49:28 +00002044
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002045 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002046}
2047
Barry Warsawfa701a81997-01-16 00:15:11 +00002048
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002049
Guido van Rossum18468821994-06-20 07:49:28 +00002050static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002051Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002052{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002053 TkappObject *self = (TkappObject*)selfptr;
2054 char *cmdName;
2055 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002057 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2058 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002059
2060#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002061 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2062 Tcl_Condition cond = NULL;
2063 CommandEvent *ev;
2064 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2065 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2066 ev->interp = self->interp;
2067 ev->create = 0;
2068 ev->name = cmdName;
2069 ev->status = &err;
2070 ev->done = &cond;
2071 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2072 &command_mutex);
2073 Tcl_ConditionFinalize(&cond);
2074 }
2075 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002076#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002077 {
2078 ENTER_TCL
2079 err = Tcl_DeleteCommand(self->interp, cmdName);
2080 LEAVE_TCL
2081 }
2082 if (err == -1) {
2083 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2084 return NULL;
2085 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002086 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002087}
2088
Barry Warsawfa701a81997-01-16 00:15:11 +00002089
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002090
Guido van Rossum00d93061998-05-28 23:06:38 +00002091#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002092/** File Handler **/
2093
Guido van Rossum00d93061998-05-28 23:06:38 +00002094typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002095 PyObject *func;
2096 PyObject *file;
2097 int id;
2098 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002099} FileHandler_ClientData;
2100
2101static FileHandler_ClientData *HeadFHCD;
2102
2103static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002104NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002105{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002106 FileHandler_ClientData *p;
2107 p = PyMem_NEW(FileHandler_ClientData, 1);
2108 if (p != NULL) {
2109 Py_XINCREF(func);
2110 Py_XINCREF(file);
2111 p->func = func;
2112 p->file = file;
2113 p->id = id;
2114 p->next = HeadFHCD;
2115 HeadFHCD = p;
2116 }
2117 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002118}
2119
2120static void
Fred Drake509d79a2000-07-08 04:04:38 +00002121DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002122{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002123 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002124
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002125 pp = &HeadFHCD;
2126 while ((p = *pp) != NULL) {
2127 if (p->id == id) {
2128 *pp = p->next;
2129 Py_XDECREF(p->func);
2130 Py_XDECREF(p->file);
2131 PyMem_DEL(p);
2132 }
2133 else
2134 pp = &p->next;
2135 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002136}
2137
Guido van Rossuma597dde1995-01-10 20:56:29 +00002138static void
Fred Drake509d79a2000-07-08 04:04:38 +00002139FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002140{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002141 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2142 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002143
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002144 ENTER_PYTHON
2145 func = data->func;
2146 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002147
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002148 arg = Py_BuildValue("(Oi)", file, (long) mask);
2149 res = PyEval_CallObject(func, arg);
2150 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002151
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002152 if (res == NULL) {
2153 errorInCmd = 1;
2154 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2155 }
2156 Py_XDECREF(res);
2157 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002158}
2159
Guido van Rossum18468821994-06-20 07:49:28 +00002160static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002161Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2162 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002163{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002164 FileHandler_ClientData *data;
2165 PyObject *file, *func;
2166 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002167
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002168 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2169 &file, &mask, &func))
2170 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002171
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002172 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002173
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002174 tfile = PyObject_AsFileDescriptor(file);
2175 if (tfile < 0)
2176 return NULL;
2177 if (!PyCallable_Check(func)) {
2178 PyErr_SetString(PyExc_TypeError, "bad argument list");
2179 return NULL;
2180 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002181
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002182 data = NewFHCD(func, file, tfile);
2183 if (data == NULL)
2184 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002185
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002186 /* Ought to check for null Tcl_File object... */
2187 ENTER_TCL
2188 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2189 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002190 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002191}
2192
2193static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002194Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002195{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002196 PyObject *file;
2197 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002198
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002199 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2200 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002201
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002202 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002203
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002204 tfile = PyObject_AsFileDescriptor(file);
2205 if (tfile < 0)
2206 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002207
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002208 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002209
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002210 /* Ought to check for null Tcl_File object... */
2211 ENTER_TCL
2212 Tcl_DeleteFileHandler(tfile);
2213 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002214 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002215}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002216#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002217
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002218
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002219/**** Tktt Object (timer token) ****/
2220
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002221static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002222
Guido van Rossum00d93061998-05-28 23:06:38 +00002223typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002224 PyObject_HEAD
2225 Tcl_TimerToken token;
2226 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002227} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002228
2229static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002230Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002231{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002232 TkttObject *v = (TkttObject *)self;
2233 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002234
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002235 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2236 return NULL;
2237 if (v->token != NULL) {
2238 Tcl_DeleteTimerHandler(v->token);
2239 v->token = NULL;
2240 }
2241 if (func != NULL) {
2242 v->func = NULL;
2243 Py_DECREF(func);
2244 Py_DECREF(v); /* See Tktt_New() */
2245 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002246 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002247}
2248
2249static PyMethodDef Tktt_methods[] =
2250{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002251 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2252 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002253};
2254
2255static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002256Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002257{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002258 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002259
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002260 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002261 if (v == NULL)
2262 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002263 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002264
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002265 Py_INCREF(func);
2266 v->token = NULL;
2267 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002269 /* Extra reference, deleted when called or when handler is deleted */
2270 Py_INCREF(v);
2271 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002272}
2273
2274static void
Fred Drake509d79a2000-07-08 04:04:38 +00002275Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002276{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002277 TkttObject *v = (TkttObject *)self;
2278 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002279 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002280
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002281 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002282
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002283 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002284 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002285}
2286
Guido van Rossum597ac201998-05-12 14:36:19 +00002287static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002288Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002289{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002290 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002291 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2292 v,
2293 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002294}
2295
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002296static PyType_Slot Tktt_Type_slots[] = {
2297 {Py_tp_dealloc, Tktt_Dealloc},
2298 {Py_tp_repr, Tktt_Repr},
2299 {Py_tp_methods, Tktt_methods},
2300 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002301};
2302
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002303static PyType_Spec Tktt_Type_spec = {
2304 "tktimertoken",
2305 sizeof(TkttObject),
2306 0,
2307 Py_TPFLAGS_DEFAULT,
2308 Tktt_Type_slots,
2309};
Barry Warsawfa701a81997-01-16 00:15:11 +00002310
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002311
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002312/** Timer Handler **/
2313
2314static void
Fred Drake509d79a2000-07-08 04:04:38 +00002315TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002316{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002317 TkttObject *v = (TkttObject *)clientData;
2318 PyObject *func = v->func;
2319 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002321 if (func == NULL)
2322 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002323
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002324 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002326 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002327
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002328 res = PyEval_CallObject(func, NULL);
2329 Py_DECREF(func);
2330 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002331
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002332 if (res == NULL) {
2333 errorInCmd = 1;
2334 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2335 }
2336 else
2337 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002338
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002339 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002340}
2341
2342static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002343Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002344{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002345 int milliseconds;
2346 PyObject *func;
2347 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002348
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002349 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2350 &milliseconds, &func))
2351 return NULL;
2352 if (!PyCallable_Check(func)) {
2353 PyErr_SetString(PyExc_TypeError, "bad argument list");
2354 return NULL;
2355 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002356
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002357 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002358
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002359 v = Tktt_New(func);
2360 if (v) {
2361 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2362 (ClientData)v);
2363 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002364
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002365 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002366}
2367
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002368
Guido van Rossum18468821994-06-20 07:49:28 +00002369/** Event Loop **/
2370
Guido van Rossum18468821994-06-20 07:49:28 +00002371static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002372Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002373{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002374 int threshold = 0;
2375 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002376#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002377 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002378#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002380 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2381 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002382
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002383 CHECK_TCL_APPARTMENT;
2384 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002385
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002386 quitMainLoop = 0;
2387 while (Tk_GetNumMainWindows() > threshold &&
2388 !quitMainLoop &&
2389 !errorInCmd)
2390 {
2391 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002392
2393#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002394 if (self->threaded) {
2395 /* Allow other Python threads to run. */
2396 ENTER_TCL
2397 result = Tcl_DoOneEvent(0);
2398 LEAVE_TCL
2399 }
2400 else {
2401 Py_BEGIN_ALLOW_THREADS
2402 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2403 tcl_tstate = tstate;
2404 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2405 tcl_tstate = NULL;
2406 if(tcl_lock)PyThread_release_lock(tcl_lock);
2407 if (result == 0)
2408 Sleep(Tkinter_busywaitinterval);
2409 Py_END_ALLOW_THREADS
2410 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002411#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002412 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002413#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002414
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002415 if (PyErr_CheckSignals() != 0) {
2416 self->dispatching = 0;
2417 return NULL;
2418 }
2419 if (result < 0)
2420 break;
2421 }
2422 self->dispatching = 0;
2423 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002424
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002425 if (errorInCmd) {
2426 errorInCmd = 0;
2427 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2428 excInCmd = valInCmd = trbInCmd = NULL;
2429 return NULL;
2430 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002431 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002432}
2433
2434static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002435Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002436{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002437 int flags = 0;
2438 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002439
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002440 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2441 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002443 ENTER_TCL
2444 rv = Tcl_DoOneEvent(flags);
2445 LEAVE_TCL
2446 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002447}
2448
2449static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002450Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002451{
2452
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002453 if (!PyArg_ParseTuple(args, ":quit"))
2454 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002456 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002457 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002458}
2459
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002460static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002461Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002462{
2463
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002464 if (!PyArg_ParseTuple(args, ":interpaddr"))
2465 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002466
Victor Stinnere1040e22013-09-05 00:22:24 +02002467 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002468}
2469
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002470static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002471Tkapp_TkInit(PyObject *self, PyObject *args)
2472{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002473 Tcl_Interp *interp = Tkapp_Interp(self);
2474 const char * _tk_exists = NULL;
2475 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002476
Guilherme Polob681df42009-02-09 22:33:59 +00002477#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002478 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2479 * first call failed.
2480 * To avoid the deadlock, we just refuse the second call through
2481 * a static variable.
2482 */
2483 if (tk_load_failed) {
2484 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2485 return NULL;
2486 }
Guilherme Polob681df42009-02-09 22:33:59 +00002487#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002488
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002489 /* We want to guard against calling Tk_Init() multiple times */
2490 CHECK_TCL_APPARTMENT;
2491 ENTER_TCL
2492 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2493 ENTER_OVERLAP
2494 if (err == TCL_ERROR) {
2495 /* This sets an exception, but we cannot return right
2496 away because we need to exit the overlap first. */
2497 Tkinter_Error(self);
2498 } else {
2499 _tk_exists = Tkapp_Result(self);
2500 }
2501 LEAVE_OVERLAP_TCL
2502 if (err == TCL_ERROR) {
2503 return NULL;
2504 }
2505 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2506 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002507 PyErr_SetString(Tkinter_TclError,
2508 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002509#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002510 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002511#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002512 return NULL;
2513 }
2514 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002515 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002516}
Barry Warsawfa701a81997-01-16 00:15:11 +00002517
Martin v. Löwisffad6332002-11-26 09:28:05 +00002518static PyObject *
2519Tkapp_WantObjects(PyObject *self, PyObject *args)
2520{
2521
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002522 int wantobjects = -1;
2523 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2524 return NULL;
2525 if (wantobjects == -1)
2526 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2527 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002528
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002529 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002530}
2531
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002532static PyObject *
2533Tkapp_WillDispatch(PyObject *self, PyObject *args)
2534{
2535
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002536 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002537
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002538 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002539}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002541
Guido van Rossum18468821994-06-20 07:49:28 +00002542/**** Tkapp Method List ****/
2543
2544static PyMethodDef Tkapp_methods[] =
2545{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002546 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2547 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2548 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002549 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002550 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2551 {"record", Tkapp_Record, METH_VARARGS},
2552 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2553 {"setvar", Tkapp_SetVar, METH_VARARGS},
2554 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2555 {"getvar", Tkapp_GetVar, METH_VARARGS},
2556 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2557 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2558 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2559 {"getint", Tkapp_GetInt, METH_VARARGS},
2560 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2561 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2562 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2563 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2564 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2565 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2566 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2567 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002568 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2569 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002570#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002571 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2572 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002573#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002574 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2575 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2576 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2577 {"quit", Tkapp_Quit, METH_VARARGS},
2578 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2579 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2580 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002581};
2582
Barry Warsawfa701a81997-01-16 00:15:11 +00002583
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002584
Guido van Rossum18468821994-06-20 07:49:28 +00002585/**** Tkapp Type Methods ****/
2586
2587static void
Fred Drake509d79a2000-07-08 04:04:38 +00002588Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002589{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002590 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002591 /*CHECK_TCL_APPARTMENT;*/
2592 ENTER_TCL
2593 Tcl_DeleteInterp(Tkapp_Interp(self));
2594 LEAVE_TCL
2595 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002596 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002597 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002598}
2599
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002600static PyType_Slot Tkapp_Type_slots[] = {
2601 {Py_tp_dealloc, Tkapp_Dealloc},
2602 {Py_tp_methods, Tkapp_methods},
2603 {0, 0}
2604};
2605
2606
2607static PyType_Spec Tkapp_Type_spec = {
2608 "tkapp",
2609 sizeof(TkappObject),
2610 0,
2611 Py_TPFLAGS_DEFAULT,
2612 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002613};
2614
Barry Warsawfa701a81997-01-16 00:15:11 +00002615
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002616
Guido van Rossum18468821994-06-20 07:49:28 +00002617/**** Tkinter Module ****/
2618
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002619typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002620 PyObject* tuple;
2621 int size; /* current size */
2622 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002623} FlattenContext;
2624
2625static int
2626_bump(FlattenContext* context, int size)
2627{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002628 /* expand tuple to hold (at least) size new items.
2629 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002631 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002633 if (maxsize < context->size + size)
2634 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002635
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002636 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002637
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002638 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002639}
2640
2641static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002642_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002643{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002644 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002645
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002646 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002648 if (depth > 1000) {
2649 PyErr_SetString(PyExc_ValueError,
2650 "nesting too deep in _flatten");
2651 return 0;
2652 } else if (PyList_Check(item)) {
2653 size = PyList_GET_SIZE(item);
2654 /* preallocate (assume no nesting) */
2655 if (context->size + size > context->maxsize &&
2656 !_bump(context, size))
2657 return 0;
2658 /* copy items to output tuple */
2659 for (i = 0; i < size; i++) {
2660 PyObject *o = PyList_GET_ITEM(item, i);
2661 if (PyList_Check(o) || PyTuple_Check(o)) {
2662 if (!_flatten1(context, o, depth + 1))
2663 return 0;
2664 } else if (o != Py_None) {
2665 if (context->size + 1 > context->maxsize &&
2666 !_bump(context, 1))
2667 return 0;
2668 Py_INCREF(o);
2669 PyTuple_SET_ITEM(context->tuple,
2670 context->size++, o);
2671 }
2672 }
2673 } else if (PyTuple_Check(item)) {
2674 /* same, for tuples */
2675 size = PyTuple_GET_SIZE(item);
2676 if (context->size + size > context->maxsize &&
2677 !_bump(context, size))
2678 return 0;
2679 for (i = 0; i < size; i++) {
2680 PyObject *o = PyTuple_GET_ITEM(item, i);
2681 if (PyList_Check(o) || PyTuple_Check(o)) {
2682 if (!_flatten1(context, o, depth + 1))
2683 return 0;
2684 } else if (o != Py_None) {
2685 if (context->size + 1 > context->maxsize &&
2686 !_bump(context, 1))
2687 return 0;
2688 Py_INCREF(o);
2689 PyTuple_SET_ITEM(context->tuple,
2690 context->size++, o);
2691 }
2692 }
2693 } else {
2694 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2695 return 0;
2696 }
2697 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002698}
2699
2700static PyObject *
2701Tkinter_Flatten(PyObject* self, PyObject* args)
2702{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002703 FlattenContext context;
2704 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002705
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002706 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2707 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002708
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002709 context.maxsize = PySequence_Size(item);
2710 if (context.maxsize < 0)
2711 return NULL;
2712 if (context.maxsize == 0)
2713 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002714
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002715 context.tuple = PyTuple_New(context.maxsize);
2716 if (!context.tuple)
2717 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002718
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002719 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002720
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002721 if (!_flatten1(&context, item,0))
2722 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002723
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002724 if (_PyTuple_Resize(&context.tuple, context.size))
2725 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002726
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002727 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002728}
2729
Guido van Rossum18468821994-06-20 07:49:28 +00002730static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002731Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002732{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002733 char *screenName = NULL;
2734 char *baseName = NULL; /* XXX this is not used anymore;
2735 try getting rid of it. */
2736 char *className = NULL;
2737 int interactive = 0;
2738 int wantobjects = 0;
2739 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2740 int sync = 0; /* pass -sync to wish */
2741 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002743 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002744
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002745 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2746 &screenName, &baseName, &className,
2747 &interactive, &wantobjects, &wantTk,
2748 &sync, &use))
2749 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002750
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002751 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002752 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002753 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002754}
2755
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002756static PyObject *
2757Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2758{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002759 int new_val;
2760 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2761 return NULL;
2762 if (new_val < 0) {
2763 PyErr_SetString(PyExc_ValueError,
2764 "busywaitinterval must be >= 0");
2765 return NULL;
2766 }
2767 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002768 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002769}
2770
2771static char setbusywaitinterval_doc[] =
2772"setbusywaitinterval(n) -> None\n\
2773\n\
2774Set the busy-wait interval in milliseconds between successive\n\
2775calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2776It should be set to a divisor of the maximum time between\n\
2777frames in an animation.";
2778
2779static PyObject *
2780Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2781{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002782 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002783}
2784
2785static char getbusywaitinterval_doc[] =
2786"getbusywaitinterval() -> int\n\
2787\n\
2788Return the current busy-wait interval between successive\n\
2789calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2790
Guido van Rossum18468821994-06-20 07:49:28 +00002791static PyMethodDef moduleMethods[] =
2792{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002793 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2794 {"create", Tkinter_Create, METH_VARARGS},
2795 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2796 setbusywaitinterval_doc},
2797 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2798 METH_NOARGS, getbusywaitinterval_doc},
2799 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002800};
2801
Guido van Rossum7bf15641998-05-22 18:28:17 +00002802#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002803
2804static int stdin_ready = 0;
2805
Guido van Rossumad4db171998-06-13 13:56:28 +00002806#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002807static void
Fred Drake509d79a2000-07-08 04:04:38 +00002808MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002809{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002810 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002811}
Guido van Rossumad4db171998-06-13 13:56:28 +00002812#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002813
Martin v. Löwisa9656492003-03-30 08:44:58 +00002814#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002815static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002816#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002817
Guido van Rossum18468821994-06-20 07:49:28 +00002818static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002819EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002820{
Guido van Rossumad4db171998-06-13 13:56:28 +00002821#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002822 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002823#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002824#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002825 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002826#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002827 stdin_ready = 0;
2828 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002829#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002830 tfile = fileno(stdin);
2831 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002832#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002833 while (!errorInCmd && !stdin_ready) {
2834 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002835#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002836 if (_kbhit()) {
2837 stdin_ready = 1;
2838 break;
2839 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002840#endif
2841#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002842 Py_BEGIN_ALLOW_THREADS
2843 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2844 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002845
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002846 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002847
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002848 tcl_tstate = NULL;
2849 if(tcl_lock)PyThread_release_lock(tcl_lock);
2850 if (result == 0)
2851 Sleep(Tkinter_busywaitinterval);
2852 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002853#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002854 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002855#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002856
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002857 if (result < 0)
2858 break;
2859 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002860#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002861 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002862#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002863 if (errorInCmd) {
2864 errorInCmd = 0;
2865 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2866 excInCmd = valInCmd = trbInCmd = NULL;
2867 PyErr_Print();
2868 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002869#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002870 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002871#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002872 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002873}
Guido van Rossum18468821994-06-20 07:49:28 +00002874
Guido van Rossum00d93061998-05-28 23:06:38 +00002875#endif
2876
Guido van Rossum7bf15641998-05-22 18:28:17 +00002877static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002878EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002879{
Guido van Rossum00d93061998-05-28 23:06:38 +00002880#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002881 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002882#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002883 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002884#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002885 PyOS_InputHook = EventHook;
2886 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002887#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002888}
2889
2890static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002891DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002892{
Guido van Rossum00d93061998-05-28 23:06:38 +00002893#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002894 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2895 PyOS_InputHook = NULL;
2896 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002897#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002898}
2899
Barry Warsawfa701a81997-01-16 00:15:11 +00002900
Martin v. Löwis1a214512008-06-11 05:26:20 +00002901static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002902 PyModuleDef_HEAD_INIT,
2903 "_tkinter",
2904 NULL,
2905 -1,
2906 moduleMethods,
2907 NULL,
2908 NULL,
2909 NULL,
2910 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002911};
2912
Mark Hammond62b1ab12002-07-23 06:31:15 +00002913PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002914PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002915{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002916 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00002917
Guido van Rossum00d93061998-05-28 23:06:38 +00002918#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002919 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002920 if (tcl_lock == NULL)
2921 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002922#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002923
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002924 m = PyModule_Create(&_tkintermodule);
2925 if (m == NULL)
2926 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002927
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002928 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
2929 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02002930 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002931 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02002932 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002933 Py_INCREF(o);
2934 if (PyModule_AddObject(m, "TclError", o)) {
2935 Py_DECREF(o);
2936 Py_DECREF(m);
2937 return NULL;
2938 }
2939 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002940
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002941 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
2942 Py_DECREF(m);
2943 return NULL;
2944 }
2945 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
2946 Py_DECREF(m);
2947 return NULL;
2948 }
2949 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
2950 Py_DECREF(m);
2951 return NULL;
2952 }
2953 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
2954 Py_DECREF(m);
2955 return NULL;
2956 }
2957 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
2958 Py_DECREF(m);
2959 return NULL;
2960 }
2961 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
2962 Py_DECREF(m);
2963 return NULL;
2964 }
2965 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
2966 Py_DECREF(m);
2967 return NULL;
2968 }
2969 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
2970 Py_DECREF(m);
2971 return NULL;
2972 }
2973 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
2974 Py_DECREF(m);
2975 return NULL;
2976 }
2977 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
2978 Py_DECREF(m);
2979 return NULL;
2980 }
2981 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
2982 Py_DECREF(m);
2983 return NULL;
2984 }
2985
2986 o = PyType_FromSpec(&Tkapp_Type_spec);
2987 if (o == NULL) {
2988 Py_DECREF(m);
2989 return NULL;
2990 }
2991 if (PyModule_AddObject(m, "TkappType", o)) {
2992 Py_DECREF(o);
2993 Py_DECREF(m);
2994 return NULL;
2995 }
2996 Tkapp_Type = o;
2997
2998 o = PyType_FromSpec(&Tktt_Type_spec);
2999 if (o == NULL) {
3000 Py_DECREF(m);
3001 return NULL;
3002 }
3003 if (PyModule_AddObject(m, "TkttType", o)) {
3004 Py_DECREF(o);
3005 Py_DECREF(m);
3006 return NULL;
3007 }
3008 Tktt_Type = o;
3009
3010 o = PyType_FromSpec(&PyTclObject_Type_spec);
3011 if (o == NULL) {
3012 Py_DECREF(m);
3013 return NULL;
3014 }
3015 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3016 Py_DECREF(o);
3017 Py_DECREF(m);
3018 return NULL;
3019 }
3020 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003021
3022#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003023 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3024 * start waking up. Note that Tcl_FindExecutable will do this, this
3025 * code must be above it! The original warning from
3026 * tkMacOSXAppInit.c is copied below.
3027 *
3028 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3029 * Tcl interpreter for now. It probably should work to do this
3030 * in the other order, but for now it doesn't seem to.
3031 *
3032 */
3033 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003034#endif
3035
3036
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003037 /* This helps the dynamic loader; in Unicode aware Tcl versions
3038 it also helps Tcl find its encodings. */
3039 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3040 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003041 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003042 if (cexe)
3043 Tcl_FindExecutable(PyBytes_AsString(cexe));
3044 Py_XDECREF(cexe);
3045 Py_DECREF(uexe);
3046 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003047
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003048 if (PyErr_Occurred()) {
3049 Py_DECREF(m);
3050 return NULL;
3051 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003052
Guido van Rossum43ff8681998-07-14 18:02:13 +00003053#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003054 /* This was not a good idea; through <Destroy> bindings,
3055 Tcl_Finalize() may invoke Python code but at that point the
3056 interpreter and thread state have already been destroyed! */
3057 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003058#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003059 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003060}