blob: eb148274733a6972c64aedc83e2a3867de606578 [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
Martin v. Löwis71e25a02002-10-01 18:08:06 +000050/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
51 making _tkinter correct for this API means to break earlier
52 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
53 earlier versions. Once Tcl releases before 8.4 don't need to be supported
54 anymore, this should go. */
55#define USE_COMPAT_CONST
56
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000057/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
58 it always; if Tcl is not threaded, the thread functions in
59 Tcl are empty. */
60#define TCL_THREADS
61
Jack Jansencb852442001-12-09 23:15:56 +000062#ifdef TK_FRAMEWORK
63#include <Tcl/tcl.h>
64#include <Tk/tk.h>
65#else
Guido van Rossum18468821994-06-20 07:49:28 +000066#include <tcl.h>
67#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000068#endif
Guido van Rossum18468821994-06-20 07:49:28 +000069
Guilherme Polo2d87e422009-04-10 22:19:09 +000070#include "tkinter.h"
71
Jason Tishlerbbe89612002-12-31 20:30:46 +000072/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000073#ifndef CONST84_RETURN
74#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000075#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000076#define CONST
77#endif
78
Guilherme Polo66917722009-02-09 22:35:27 +000079#if TK_VERSION_HEX < 0x08030102
80#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000081#endif
82
Jack Janseneddc1442003-11-20 01:44:59 +000083#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000084#define HAVE_CREATEFILEHANDLER
85#endif
86
Guido van Rossum00d93061998-05-28 23:06:38 +000087#ifdef HAVE_CREATEFILEHANDLER
88
Neal Norwitzd948a432006-01-08 01:08:55 +000089/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
90 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
91#ifndef TCL_UNIX_FD
92# ifdef TCL_WIN_SOCKET
93# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
94# else
95# define TCL_UNIX_FD 1
96# endif
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099/* Tcl_CreateFileHandler() changed several times; these macros deal with the
100 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
101 Unix, only because Jack added it back); when available on Windows, it only
102 applies to sockets. */
103
Guido van Rossum7bf15641998-05-22 18:28:17 +0000104#ifdef MS_WINDOWS
105#define FHANDLETYPE TCL_WIN_SOCKET
106#else
107#define FHANDLETYPE TCL_UNIX_FD
108#endif
109
Guido van Rossum00d93061998-05-28 23:06:38 +0000110/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
111 which uses this to handle Tcl events while the user is typing commands. */
112
113#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000114#define WAIT_FOR_STDIN
115#endif
116
Guido van Rossum00d93061998-05-28 23:06:38 +0000117#endif /* HAVE_CREATEFILEHANDLER */
118
Guido van Rossumad4db171998-06-13 13:56:28 +0000119#ifdef MS_WINDOWS
120#include <conio.h>
121#define WAIT_FOR_STDIN
122#endif
123
Guido van Rossum00d93061998-05-28 23:06:38 +0000124#ifdef WITH_THREAD
125
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000126/* The threading situation is complicated. Tcl is not thread-safe, except
127 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000128
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300129 So we need to use a lock around all uses of Tcl. Previously, the
130 Python interpreter lock was used for this. However, this causes
131 problems when other Python threads need to run while Tcl is blocked
132 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000133
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300134 To solve this problem, a separate lock for Tcl is introduced.
135 Holding it is incompatible with holding Python's interpreter lock.
136 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000137
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300138 ENTER_TCL and LEAVE_TCL are brackets, just like
139 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
140 used whenever a call into Tcl is made that could call an event
141 handler, or otherwise affect the state of a Tcl interpreter. These
142 assume that the surrounding code has the Python interpreter lock;
143 inside the brackets, the Python interpreter lock has been released
144 and the lock for Tcl has been acquired.
145
146 Sometimes, it is necessary to have both the Python lock and the Tcl
147 lock. (For example, when transferring data from the Tcl
148 interpreter result to a Python string object.) This can be done by
149 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
150 reacquires the Python lock (and restores the thread state) but
151 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
152 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000153
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000154 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300155 handlers when the handler needs to use Python. Such event handlers
156 are entered while the lock for Tcl is held; the event handler
157 presumably needs to use Python. ENTER_PYTHON releases the lock for
158 Tcl and acquires the Python interpreter lock, restoring the
159 appropriate thread state, and LEAVE_PYTHON releases the Python
160 interpreter lock and re-acquires the lock for Tcl. It is okay for
161 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
162 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000163
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300164 These locks expand to several statements and brackets; they should
165 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000166
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300167 If Tcl is threaded, this approach won't work anymore. The Tcl
168 interpreter is only valid in the thread that created it, and all Tk
169 activity must happen in this thread, also. That means that the
170 mainloop must be invoked in the thread that created the
171 interpreter. Invoking commands from other threads is possible;
172 _tkinter will queue an event for the interpreter thread, which will
173 then execute the command and pass back the result. If the main
174 thread is not in the mainloop, and invoking commands causes an
175 exception; if the main loop is running but not processing events,
176 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000177
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300178 In addition, for a threaded Tcl, a single global tcl_tstate won't
179 be sufficient anymore, since multiple Tcl interpreters may
180 simultaneously dispatch in different threads. So we use the Tcl TLS
181 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000182
Guido van Rossum00d93061998-05-28 23:06:38 +0000183*/
184
Guido van Rossum65d5b571998-12-21 19:32:43 +0000185static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000186
187#ifdef TCL_THREADS
188static Tcl_ThreadDataKey state_key;
189typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300190#define tcl_tstate \
191 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000192#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000193static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000194#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000195
196#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000197 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
198 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000199
200#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300201 tcl_tstate = NULL; \
202 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000203
Guido van Rossum62320c91998-06-15 04:36:09 +0000204#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000206
207#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000208 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000209
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000210#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000211 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300212 if(tcl_lock) \
213 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000214
215#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000216 { PyThreadState *tstate = PyEval_SaveThread(); \
217 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000218
219#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000220 if (((TkappObject *)self)->threaded && \
221 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300222 PyErr_SetString(PyExc_RuntimeError, \
223 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000224 return 0; \
225 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000226
227#else
228
229#define ENTER_TCL
230#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000231#define ENTER_OVERLAP
232#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000233#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000234#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000235#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000236
237#endif
238
Guido van Rossum97867b21996-08-08 19:09:53 +0000239#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000240#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000241#endif
242
Guido van Rossum18468821994-06-20 07:49:28 +0000243/**** Tkapp Object Declaration ****/
244
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300245static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000246
Guido van Rossum00d93061998-05-28 23:06:38 +0000247typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000248 PyObject_HEAD
249 Tcl_Interp *interp;
250 int wantobjects;
251 int threaded; /* True if tcl_platform[threaded] */
252 Tcl_ThreadId thread_id;
253 int dispatching;
254 /* We cannot include tclInt.h, as this is internal.
255 So we cache interesting types here. */
256 Tcl_ObjType *BooleanType;
257 Tcl_ObjType *ByteArrayType;
258 Tcl_ObjType *DoubleType;
259 Tcl_ObjType *IntType;
260 Tcl_ObjType *ListType;
261 Tcl_ObjType *ProcBodyType;
262 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000263} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000264
Guido van Rossum18468821994-06-20 07:49:28 +0000265#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000266#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000267
Guido van Rossum35d43371997-08-02 00:09:09 +0000268#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000269(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000270
Barry Warsawfa701a81997-01-16 00:15:11 +0000271
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000272
Guido van Rossum18468821994-06-20 07:49:28 +0000273/**** Error Handling ****/
274
275static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000276static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000277static int errorInCmd = 0;
278static PyObject *excInCmd;
279static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000280static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000281
Guilherme Polob681df42009-02-09 22:33:59 +0000282#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000283static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000284#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000285
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000286
Guido van Rossum18468821994-06-20 07:49:28 +0000287static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000288Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000289{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000290 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
291 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000292}
293
Barry Warsawfa701a81997-01-16 00:15:11 +0000294
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000295
Guido van Rossum18468821994-06-20 07:49:28 +0000296/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000297
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000298static int Tkinter_busywaitinterval = 20;
299
Guido van Rossum00d93061998-05-28 23:06:38 +0000300#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000301#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000302
Guido van Rossum00d93061998-05-28 23:06:38 +0000303/* Millisecond sleep() for Unix platforms. */
304
305static void
Fred Drake509d79a2000-07-08 04:04:38 +0000306Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000307{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000308 /* XXX Too bad if you don't have select(). */
309 struct timeval t;
310 t.tv_sec = milli/1000;
311 t.tv_usec = (milli%1000) * 1000;
312 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000313}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000314#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000315
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000316/* Wait up to 1s for the mainloop to come up. */
317
318static int
319WaitForMainloop(TkappObject* self)
320{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000321 int i;
322 for (i = 0; i < 10; i++) {
323 if (self->dispatching)
324 return 1;
325 Py_BEGIN_ALLOW_THREADS
326 Sleep(100);
327 Py_END_ALLOW_THREADS
328 }
329 if (self->dispatching)
330 return 1;
331 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
332 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000333}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000334#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000336
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000337
Guido van Rossum18468821994-06-20 07:49:28 +0000338#define ARGSZ 64
339
Barry Warsawfa701a81997-01-16 00:15:11 +0000340
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000341
Guido van Rossum18468821994-06-20 07:49:28 +0000342static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000343Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000344{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000345 int argc;
346 char **argv;
347 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000348
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000349 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300350 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000351 }
Guido van Rossum18468821994-06-20 07:49:28 +0000352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000353 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
354 /* Not a list.
355 * Could be a quoted string containing funnies, e.g. {"}.
356 * Return the string itself.
357 */
358 return PyUnicode_FromString(list);
359 }
Guido van Rossum18468821994-06-20 07:49:28 +0000360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000361 if (argc == 0)
362 v = PyUnicode_FromString("");
363 else if (argc == 1)
364 v = PyUnicode_FromString(argv[0]);
365 else if ((v = PyTuple_New(argc)) != NULL) {
366 int i;
367 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000368
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000369 for (i = 0; i < argc; i++) {
370 if ((w = Split(argv[i])) == NULL) {
371 Py_DECREF(v);
372 v = NULL;
373 break;
374 }
375 PyTuple_SetItem(v, i, w);
376 }
377 }
378 Tcl_Free(FREECAST argv);
379 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000380}
381
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300382/* In some cases, Tcl will still return strings that are supposed to
383 be lists. SplitObj walks through a nested tuple, finding string
384 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000385
Martin v. Löwis59683e82008-06-13 07:50:45 +0000386static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000387SplitObj(PyObject *arg)
388{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000389 if (PyTuple_Check(arg)) {
390 int i, size;
391 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000393 size = PyTuple_Size(arg);
394 result = NULL;
395 /* Recursively invoke SplitObj for all tuple items.
396 If this does not return a new object, no action is
397 needed. */
398 for(i = 0; i < size; i++) {
399 elem = PyTuple_GetItem(arg, i);
400 newelem = SplitObj(elem);
401 if (!newelem) {
402 Py_XDECREF(result);
403 return NULL;
404 }
405 if (!result) {
406 int k;
407 if (newelem == elem) {
408 Py_DECREF(newelem);
409 continue;
410 }
411 result = PyTuple_New(size);
412 if (!result)
413 return NULL;
414 for(k = 0; k < i; k++) {
415 elem = PyTuple_GetItem(arg, k);
416 Py_INCREF(elem);
417 PyTuple_SetItem(result, k, elem);
418 }
419 }
420 PyTuple_SetItem(result, i, newelem);
421 }
422 if (result)
423 return result;
424 /* Fall through, returning arg. */
425 }
426 else if (PyBytes_Check(arg)) {
427 int argc;
428 char **argv;
429 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000430
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000431 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
432 Py_INCREF(arg);
433 return arg;
434 }
435 Tcl_Free(FREECAST argv);
436 if (argc > 1)
437 return Split(PyBytes_AsString(arg));
438 /* Fall through, returning arg. */
439 }
440 Py_INCREF(arg);
441 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000442}
Barry Warsawfa701a81997-01-16 00:15:11 +0000443
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000444
Guido van Rossum18468821994-06-20 07:49:28 +0000445/**** Tkapp Object ****/
446
447#ifndef WITH_APPINIT
448int
Fred Drake509d79a2000-07-08 04:04:38 +0000449Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000450{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000451 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000452
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000453 if (Tcl_Init(interp) == TCL_ERROR) {
454 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
455 return TCL_ERROR;
456 }
Guilherme Polob681df42009-02-09 22:33:59 +0000457
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000458 _tkinter_skip_tk_init = Tcl_GetVar(interp,
459 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
460 if (_tkinter_skip_tk_init != NULL &&
461 strcmp(_tkinter_skip_tk_init, "1") == 0) {
462 return TCL_OK;
463 }
Guilherme Polob681df42009-02-09 22:33:59 +0000464
465#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 if (tk_load_failed) {
467 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
468 return TCL_ERROR;
469 }
Guilherme Polob681df42009-02-09 22:33:59 +0000470#endif
471
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000472 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000473#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000474 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000475#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000476 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
477 return TCL_ERROR;
478 }
Guilherme Polob681df42009-02-09 22:33:59 +0000479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000480 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000481}
482#endif /* !WITH_APPINIT */
483
Guido van Rossum18468821994-06-20 07:49:28 +0000484
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000485
Barry Warsawfa701a81997-01-16 00:15:11 +0000486
487/* Initialize the Tk application; see the `main' function in
488 * `tkMain.c'.
489 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000490
Thomas Wouters58d05102000-07-24 14:43:35 +0000491static void EnableEventHook(void); /* Forward */
492static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000493
Barry Warsawfa701a81997-01-16 00:15:11 +0000494static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000495Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000496 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000497{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000498 TkappObject *v;
499 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000500
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300501 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000502 if (v == NULL)
503 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000504
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000505 v->interp = Tcl_CreateInterp();
506 v->wantobjects = wantobjects;
507 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
508 TCL_GLOBAL_ONLY) != NULL;
509 v->thread_id = Tcl_GetCurrentThread();
510 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000511
512#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300514 PyErr_SetString(PyExc_RuntimeError,
515 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000516 Py_DECREF(v);
517 return 0;
518 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000519#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000520#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000521 if (v->threaded && tcl_lock) {
522 /* If Tcl is threaded, we don't need the lock. */
523 PyThread_free_lock(tcl_lock);
524 tcl_lock = NULL;
525 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000526#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000527
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000528 v->BooleanType = Tcl_GetObjType("boolean");
529 v->ByteArrayType = Tcl_GetObjType("bytearray");
530 v->DoubleType = Tcl_GetObjType("double");
531 v->IntType = Tcl_GetObjType("int");
532 v->ListType = Tcl_GetObjType("list");
533 v->ProcBodyType = Tcl_GetObjType("procbody");
534 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000535
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000536 /* Delete the 'exit' command, which can screw things up */
537 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000539 if (screenName != NULL)
540 Tcl_SetVar2(v->interp, "env", "DISPLAY",
541 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000542
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000543 if (interactive)
544 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
545 else
546 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000548 /* This is used to get the application class for Tk 4.1 and up */
549 argv0 = (char*)ckalloc(strlen(className) + 1);
550 if (!argv0) {
551 PyErr_NoMemory();
552 Py_DECREF(v);
553 return NULL;
554 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000555
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000556 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200557 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
558 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000559 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
560 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000561
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 if (! wantTk) {
563 Tcl_SetVar(v->interp,
564 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
565 }
Guilherme Polob681df42009-02-09 22:33:59 +0000566#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 else if (tk_load_failed) {
568 Tcl_SetVar(v->interp,
569 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
570 }
Guilherme Polob681df42009-02-09 22:33:59 +0000571#endif
David Aschere2b4b322004-02-18 05:59:53 +0000572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000573 /* some initial arguments need to be in argv */
574 if (sync || use) {
575 char *args;
576 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000578 if (sync)
579 len += sizeof "-sync";
580 if (use)
581 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000582
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000583 args = (char*)ckalloc(len);
584 if (!args) {
585 PyErr_NoMemory();
586 Py_DECREF(v);
587 return NULL;
588 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000589
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000590 args[0] = '\0';
591 if (sync)
592 strcat(args, "-sync");
593 if (use) {
594 if (sync)
595 strcat(args, " ");
596 strcat(args, "-use ");
597 strcat(args, use);
598 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000600 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
601 ckfree(args);
602 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000603
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000604 if (Tcl_AppInit(v->interp) != TCL_OK) {
605 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000606#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 if (wantTk) {
608 const char *_tkinter_tk_failed;
609 _tkinter_tk_failed = Tcl_GetVar(v->interp,
610 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 if ( _tkinter_tk_failed != NULL &&
613 strcmp(_tkinter_tk_failed, "1") == 0) {
614 tk_load_failed = 1;
615 }
616 }
Guilherme Polob681df42009-02-09 22:33:59 +0000617#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 Py_DECREF((PyObject *)v);
619 return (TkappObject *)result;
620 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000621
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000622 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000623
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000624 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000625}
626
Barry Warsawfa701a81997-01-16 00:15:11 +0000627
Benjamin Peterson5879d412009-03-30 14:51:56 +0000628#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000629static void
630Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000631 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000632{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 Py_BEGIN_ALLOW_THREADS;
634 Tcl_MutexLock(mutex);
635 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
636 Tcl_ThreadAlert(self->thread_id);
637 Tcl_ConditionWait(cond, mutex, NULL);
638 Tcl_MutexUnlock(mutex);
639 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000640}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000641#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000643
Guido van Rossum18468821994-06-20 07:49:28 +0000644/** Tcl Eval **/
645
Martin v. Löwisffad6332002-11-26 09:28:05 +0000646typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 PyObject_HEAD
648 Tcl_Obj *value;
649 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000650} PyTclObject;
651
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300652static PyObject *PyTclObject_Type;
653#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000654
655static PyObject *
656newPyTclObject(Tcl_Obj *arg)
657{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300659 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 if (self == NULL)
661 return NULL;
662 Tcl_IncrRefCount(arg);
663 self->value = arg;
664 self->string = NULL;
665 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000666}
667
668static void
669PyTclObject_dealloc(PyTclObject *self)
670{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000671 Tcl_DecrRefCount(self->value);
672 Py_XDECREF(self->string);
673 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000674}
675
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000676static char*
677PyTclObject_TclString(PyObject *self)
678{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000679 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000680}
681
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000682/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000683PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000684"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000685
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000686static PyObject *
687PyTclObject_string(PyTclObject *self, void *ignored)
688{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000689 char *s;
690 int len;
691 if (!self->string) {
692 s = Tcl_GetStringFromObj(self->value, &len);
693 self->string = PyUnicode_FromStringAndSize(s, len);
694 if (!self->string)
695 return NULL;
696 }
697 Py_INCREF(self->string);
698 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000699}
700
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000701static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000702PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000703{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000704 char *s;
705 int len;
706 if (self->string && PyUnicode_Check(self->string)) {
707 Py_INCREF(self->string);
708 return self->string;
709 }
710 /* XXX Could chache result if it is non-ASCII. */
711 s = Tcl_GetStringFromObj(self->value, &len);
712 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000713}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000714
Martin v. Löwisffad6332002-11-26 09:28:05 +0000715static PyObject *
716PyTclObject_repr(PyTclObject *self)
717{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 return PyUnicode_FromFormat("<%s object at %p>",
719 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000720}
721
Mark Dickinson211c6252009-02-01 10:28:51 +0000722#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
723
724static PyObject *
725PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000726{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000727 int result;
728 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000729
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000730 /* neither argument should be NULL, unless something's gone wrong */
731 if (self == NULL || other == NULL) {
732 PyErr_BadInternalCall();
733 return NULL;
734 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000735
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000736 /* both arguments should be instances of PyTclObject */
737 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
738 v = Py_NotImplemented;
739 goto finished;
740 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000741
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 if (self == other)
743 /* fast path when self and other are identical */
744 result = 0;
745 else
746 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
747 Tcl_GetString(((PyTclObject *)other)->value));
748 /* Convert return value to a Boolean */
749 switch (op) {
750 case Py_EQ:
751 v = TEST_COND(result == 0);
752 break;
753 case Py_NE:
754 v = TEST_COND(result != 0);
755 break;
756 case Py_LE:
757 v = TEST_COND(result <= 0);
758 break;
759 case Py_GE:
760 v = TEST_COND(result >= 0);
761 break;
762 case Py_LT:
763 v = TEST_COND(result < 0);
764 break;
765 case Py_GT:
766 v = TEST_COND(result > 0);
767 break;
768 default:
769 PyErr_BadArgument();
770 return NULL;
771 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000772 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000773 Py_INCREF(v);
774 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000775}
776
Martin v. Löwis39195712003-01-04 00:33:13 +0000777PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
778
Martin v. Löwisffad6332002-11-26 09:28:05 +0000779static PyObject*
780get_typename(PyTclObject* obj, void* ignored)
781{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000782 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000783}
784
Martin v. Löwis39195712003-01-04 00:33:13 +0000785
Martin v. Löwisffad6332002-11-26 09:28:05 +0000786static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000787 {"typename", (getter)get_typename, NULL, get_typename__doc__},
788 {"string", (getter)PyTclObject_string, NULL,
789 PyTclObject_string__doc__},
790 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000791};
792
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300793static PyType_Slot PyTclObject_Type_slots[] = {
794 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
795 {Py_tp_repr, (reprfunc)PyTclObject_repr},
796 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200797 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300798 {Py_tp_richcompare, PyTclObject_richcompare},
799 {Py_tp_getset, PyTclObject_getsetlist},
800 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000801};
802
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300803static PyType_Spec PyTclObject_Type_spec = {
804 "_tkinter.Tcl_Obj",
805 sizeof(PyTclObject),
806 0,
807 Py_TPFLAGS_DEFAULT,
808 PyTclObject_Type_slots,
809};
810
811
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000812static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000813AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000814{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000815 Tcl_Obj *result;
816 long longVal;
817 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000818
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000819 if (PyBytes_Check(value))
820 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
821 PyBytes_GET_SIZE(value));
822 else if (PyBool_Check(value))
823 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
824 else if (PyLong_CheckExact(value) &&
825 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
826 !overflow)) {
827 /* If there is an overflow in the long conversion,
828 fall through to default object handling. */
829 return Tcl_NewLongObj(longVal);
830 }
831 else if (PyFloat_Check(value))
832 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
833 else if (PyTuple_Check(value)) {
834 Tcl_Obj **argv = (Tcl_Obj**)
835 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
836 int i;
837 if(!argv)
838 return 0;
839 for(i=0;i<PyTuple_Size(value);i++)
840 argv[i] = AsObj(PyTuple_GetItem(value,i));
841 result = Tcl_NewListObj(PyTuple_Size(value), argv);
842 ckfree(FREECAST argv);
843 return result;
844 }
845 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200846 void *inbuf;
847 Py_ssize_t size;
848 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000849 Tcl_UniChar *outbuf = NULL;
850 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200851 size_t allocsize;
852
853 if (PyUnicode_READY(value) == -1)
854 return NULL;
855
856 inbuf = PyUnicode_DATA(value);
857 size = PyUnicode_GET_LENGTH(value);
858 kind = PyUnicode_KIND(value);
859 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
860 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000861 /* Else overflow occurred, and we take the next exit */
862 if (!outbuf) {
863 PyErr_NoMemory();
864 return NULL;
865 }
866 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200867 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
868 /* We cannot test for sizeof(Tcl_UniChar) directly,
869 so we test for UTF-8 size instead. */
870#if TCL_UTF_MAX == 3
871 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000872 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200873 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100874 "character U+%x is above the range "
875 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100876 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000877 ckfree(FREECAST outbuf);
878 return NULL;
879 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300880#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200881 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000882 }
883 result = Tcl_NewUnicodeObj(outbuf, size);
884 ckfree(FREECAST outbuf);
885 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000886 }
887 else if(PyTclObject_Check(value)) {
888 Tcl_Obj *v = ((PyTclObject*)value)->value;
889 Tcl_IncrRefCount(v);
890 return v;
891 }
892 else {
893 PyObject *v = PyObject_Str(value);
894 if (!v)
895 return 0;
896 result = AsObj(v);
897 Py_DECREF(v);
898 return result;
899 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000900}
901
Martin v. Löwisffad6332002-11-26 09:28:05 +0000902static PyObject*
903FromObj(PyObject* tkapp, Tcl_Obj *value)
904{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000905 PyObject *result = NULL;
906 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000907
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000908 if (value->typePtr == NULL) {
909 return PyUnicode_FromStringAndSize(value->bytes,
910 value->length);
911 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000912
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000913 if (value->typePtr == app->BooleanType) {
914 result = value->internalRep.longValue ? Py_True : Py_False;
915 Py_INCREF(result);
916 return result;
917 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000918
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000919 if (value->typePtr == app->ByteArrayType) {
920 int size;
921 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
922 return PyBytes_FromStringAndSize(data, size);
923 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000924
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000925 if (value->typePtr == app->DoubleType) {
926 return PyFloat_FromDouble(value->internalRep.doubleValue);
927 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000928
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000929 if (value->typePtr == app->IntType) {
930 return PyLong_FromLong(value->internalRep.longValue);
931 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000932
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000933 if (value->typePtr == app->ListType) {
934 int size;
935 int i, status;
936 PyObject *elem;
937 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000938
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000939 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
940 if (status == TCL_ERROR)
941 return Tkinter_Error(tkapp);
942 result = PyTuple_New(size);
943 if (!result)
944 return NULL;
945 for (i = 0; i < size; i++) {
946 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
947 value, i, &tcl_elem);
948 if (status == TCL_ERROR) {
949 Py_DECREF(result);
950 return Tkinter_Error(tkapp);
951 }
952 elem = FromObj(tkapp, tcl_elem);
953 if (!elem) {
954 Py_DECREF(result);
955 return NULL;
956 }
957 PyTuple_SetItem(result, i, elem);
958 }
959 return result;
960 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000961
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000962 if (value->typePtr == app->ProcBodyType) {
963 /* fall through: return tcl object. */
964 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000965
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000966 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200967#if TCL_UTF_MAX==3
968 return PyUnicode_FromKindAndData(
969 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
970 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000971#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200972 return PyUnicode_FromKindAndData(
973 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
974 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000975#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000976 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000977
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000978 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000979}
980
Benjamin Peterson5879d412009-03-30 14:51:56 +0000981#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000982/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000983TCL_DECLARE_MUTEX(call_mutex)
984
985typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000986 Tcl_Event ev; /* Must be first */
987 TkappObject *self;
988 PyObject *args;
989 int flags;
990 PyObject **res;
991 PyObject **exc_type, **exc_value, **exc_tb;
992 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000993} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +0000994#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000995
996void
997Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +0000998{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000999 int i;
1000 for (i = 0; i < objc; i++)
1001 Tcl_DecrRefCount(objv[i]);
1002 if (objv != objStore)
1003 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001004}
Guido van Rossum18468821994-06-20 07:49:28 +00001005
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001006/* Convert Python objects to Tcl objects. This must happen in the
1007 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001008
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001009static Tcl_Obj**
1010Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1011{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001012 Tcl_Obj **objv = objStore;
1013 int objc = 0, i;
1014 if (args == NULL)
1015 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001016
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001017 else if (!PyTuple_Check(args)) {
1018 objv[0] = AsObj(args);
1019 if (objv[0] == 0)
1020 goto finally;
1021 objc = 1;
1022 Tcl_IncrRefCount(objv[0]);
1023 }
1024 else {
1025 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001026
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001027 if (objc > ARGSZ) {
1028 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1029 if (objv == NULL) {
1030 PyErr_NoMemory();
1031 objc = 0;
1032 goto finally;
1033 }
1034 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001035
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001036 for (i = 0; i < objc; i++) {
1037 PyObject *v = PyTuple_GetItem(args, i);
1038 if (v == Py_None) {
1039 objc = i;
1040 break;
1041 }
1042 objv[i] = AsObj(v);
1043 if (!objv[i]) {
1044 /* Reset objc, so it attempts to clear
1045 objects only up to i. */
1046 objc = i;
1047 goto finally;
1048 }
1049 Tcl_IncrRefCount(objv[i]);
1050 }
1051 }
1052 *pobjc = objc;
1053 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001054finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 Tkapp_CallDeallocArgs(objv, objStore, objc);
1056 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001057}
Guido van Rossum212643f1998-04-29 16:22:14 +00001058
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001059/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001060
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001061static PyObject*
1062Tkapp_CallResult(TkappObject *self)
1063{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001064 PyObject *res = NULL;
1065 if(self->wantobjects) {
1066 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1067 /* Not sure whether the IncrRef is necessary, but something
1068 may overwrite the interpreter result while we are
1069 converting it. */
1070 Tcl_IncrRefCount(value);
1071 res = FromObj((PyObject*)self, value);
1072 Tcl_DecrRefCount(value);
1073 } else {
1074 const char *s = Tcl_GetStringResult(self->interp);
1075 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001076
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001077 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1078 }
1079 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001080}
Guido van Rossum632de272000-03-29 00:19:50 +00001081
Benjamin Peterson5879d412009-03-30 14:51:56 +00001082#ifdef WITH_THREAD
1083
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001084/* Tkapp_CallProc is the event procedure that is executed in the context of
1085 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1086 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001087
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001088static int
1089Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1090{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001091 Tcl_Obj *objStore[ARGSZ];
1092 Tcl_Obj **objv;
1093 int objc;
1094 int i;
1095 ENTER_PYTHON
1096 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1097 if (!objv) {
1098 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1099 *(e->res) = NULL;
1100 }
1101 LEAVE_PYTHON
1102 if (!objv)
1103 goto done;
1104 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1105 ENTER_PYTHON
1106 if (i == TCL_ERROR) {
1107 *(e->res) = NULL;
1108 *(e->exc_type) = NULL;
1109 *(e->exc_tb) = NULL;
1110 *(e->exc_value) = PyObject_CallFunction(
1111 Tkinter_TclError, "s",
1112 Tcl_GetStringResult(e->self->interp));
1113 }
1114 else {
1115 *(e->res) = Tkapp_CallResult(e->self);
1116 }
1117 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001118
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001119 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001120done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001121 /* Wake up calling thread. */
1122 Tcl_MutexLock(&call_mutex);
1123 Tcl_ConditionNotify(e->done);
1124 Tcl_MutexUnlock(&call_mutex);
1125 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001126}
1127
Benjamin Peterson5879d412009-03-30 14:51:56 +00001128#endif
1129
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001130/* This is the main entry point for calling a Tcl command.
1131 It supports three cases, with regard to threading:
1132 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1133 the context of the calling thread.
1134 2. Tcl is threaded, caller of the command is in the interpreter thread:
1135 Execute the command in the calling thread. Since the Tcl lock will
1136 not be used, we can merge that with case 1.
1137 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1138 the interpreter thread. Allocation of Tcl objects needs to occur in the
1139 interpreter thread, so we ship the PyObject* args to the target thread,
1140 and perform processing there. */
1141
1142static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001143Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001144{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001145 Tcl_Obj *objStore[ARGSZ];
1146 Tcl_Obj **objv = NULL;
1147 int objc, i;
1148 PyObject *res = NULL;
1149 TkappObject *self = (TkappObject*)selfptr;
1150 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001151
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001152 /* If args is a single tuple, replace with contents of tuple */
1153 if (1 == PyTuple_Size(args)){
1154 PyObject* item = PyTuple_GetItem(args, 0);
1155 if (PyTuple_Check(item))
1156 args = item;
1157 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001158#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001159 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1160 /* We cannot call the command directly. Instead, we must
1161 marshal the parameters to the interpreter thread. */
1162 Tkapp_CallEvent *ev;
1163 Tcl_Condition cond = NULL;
1164 PyObject *exc_type, *exc_value, *exc_tb;
1165 if (!WaitForMainloop(self))
1166 return NULL;
1167 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1168 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1169 ev->self = self;
1170 ev->args = args;
1171 ev->res = &res;
1172 ev->exc_type = &exc_type;
1173 ev->exc_value = &exc_value;
1174 ev->exc_tb = &exc_tb;
1175 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001176
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001177 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001178
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001179 if (res == NULL) {
1180 if (exc_type)
1181 PyErr_Restore(exc_type, exc_value, exc_tb);
1182 else
1183 PyErr_SetObject(Tkinter_TclError, exc_value);
1184 }
1185 Tcl_ConditionFinalize(&cond);
1186 }
1187 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001188#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001189 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001190
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001191 objv = Tkapp_CallArgs(args, objStore, &objc);
1192 if (!objv)
1193 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001195 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001196
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001197 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001198
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001199 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001200
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001201 if (i == TCL_ERROR)
1202 Tkinter_Error(selfptr);
1203 else
1204 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001205
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001206 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001207
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001208 Tkapp_CallDeallocArgs(objv, objStore, objc);
1209 }
1210 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001211}
1212
1213
1214static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001215Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001216{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001217 char *script;
1218 PyObject *res = NULL;
1219 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001220
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001221 if (!PyArg_ParseTuple(args, "s:eval", &script))
1222 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001223
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001224 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001225
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001226 ENTER_TCL
1227 err = Tcl_Eval(Tkapp_Interp(self), script);
1228 ENTER_OVERLAP
1229 if (err == TCL_ERROR)
1230 res = Tkinter_Error(self);
1231 else
1232 res = PyUnicode_FromString(Tkapp_Result(self));
1233 LEAVE_OVERLAP_TCL
1234 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001235}
1236
1237static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001238Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001239{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001240 char *fileName;
1241 PyObject *res = NULL;
1242 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001243
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001244 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1245 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001246
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001247 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001249 ENTER_TCL
1250 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1251 ENTER_OVERLAP
1252 if (err == TCL_ERROR)
1253 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001254
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001255 else
1256 res = PyUnicode_FromString(Tkapp_Result(self));
1257 LEAVE_OVERLAP_TCL
1258 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001259}
1260
1261static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001262Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001263{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001264 char *script;
1265 PyObject *res = NULL;
1266 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001267
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001268 if (!PyArg_ParseTuple(args, "s", &script))
1269 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001271 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001272
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001273 ENTER_TCL
1274 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1275 ENTER_OVERLAP
1276 if (err == TCL_ERROR)
1277 res = Tkinter_Error(self);
1278 else
1279 res = PyUnicode_FromString(Tkapp_Result(self));
1280 LEAVE_OVERLAP_TCL
1281 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001282}
1283
1284static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001285Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001286{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001287 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001288
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001289 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1290 return NULL;
1291 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001292
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001293 ENTER_TCL
1294 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1295 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001296
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001297 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001298}
1299
Barry Warsawfa701a81997-01-16 00:15:11 +00001300
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001301
Guido van Rossum18468821994-06-20 07:49:28 +00001302/** Tcl Variable **/
1303
Benjamin Peterson5879d412009-03-30 14:51:56 +00001304typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1305
1306#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001307TCL_DECLARE_MUTEX(var_mutex)
1308
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001309typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001310 Tcl_Event ev; /* must be first */
1311 PyObject *self;
1312 PyObject *args;
1313 int flags;
1314 EventFunc func;
1315 PyObject **res;
1316 PyObject **exc_type;
1317 PyObject **exc_val;
1318 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001319} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001320#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001321
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001322static int
1323varname_converter(PyObject *in, void *_out)
1324{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 char **out = (char**)_out;
1326 if (PyBytes_Check(in)) {
1327 *out = PyBytes_AsString(in);
1328 return 1;
1329 }
1330 if (PyUnicode_Check(in)) {
1331 *out = _PyUnicode_AsString(in);
1332 return 1;
1333 }
1334 if (PyTclObject_Check(in)) {
1335 *out = PyTclObject_TclString(in);
1336 return 1;
1337 }
1338 /* XXX: Should give diagnostics. */
1339 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001340}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001341
Benjamin Peterson5879d412009-03-30 14:51:56 +00001342#ifdef WITH_THREAD
1343
Martin v. Löwis59683e82008-06-13 07:50:45 +00001344static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001345var_perform(VarEvent *ev)
1346{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001347 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1348 if (!*(ev->res)) {
1349 PyObject *exc, *val, *tb;
1350 PyErr_Fetch(&exc, &val, &tb);
1351 PyErr_NormalizeException(&exc, &val, &tb);
1352 *(ev->exc_type) = exc;
1353 *(ev->exc_val) = val;
1354 Py_DECREF(tb);
1355 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001356
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001357}
1358
1359static int
1360var_proc(VarEvent* ev, int flags)
1361{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001362 ENTER_PYTHON
1363 var_perform(ev);
1364 Tcl_MutexLock(&var_mutex);
1365 Tcl_ConditionNotify(ev->cond);
1366 Tcl_MutexUnlock(&var_mutex);
1367 LEAVE_PYTHON
1368 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001369}
1370
Benjamin Peterson5879d412009-03-30 14:51:56 +00001371#endif
1372
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001373static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001374var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001375{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001376#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001377 TkappObject *self = (TkappObject*)selfptr;
1378 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1379 TkappObject *self = (TkappObject*)selfptr;
1380 VarEvent *ev;
1381 PyObject *res, *exc_type, *exc_val;
1382 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001384 /* The current thread is not the interpreter thread. Marshal
1385 the call to the interpreter thread, then wait for
1386 completion. */
1387 if (!WaitForMainloop(self))
1388 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001390 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001392 ev->self = selfptr;
1393 ev->args = args;
1394 ev->flags = flags;
1395 ev->func = func;
1396 ev->res = &res;
1397 ev->exc_type = &exc_type;
1398 ev->exc_val = &exc_val;
1399 ev->cond = &cond;
1400 ev->ev.proc = (Tcl_EventProc*)var_proc;
1401 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1402 Tcl_ConditionFinalize(&cond);
1403 if (!res) {
1404 PyErr_SetObject(exc_type, exc_val);
1405 Py_DECREF(exc_type);
1406 Py_DECREF(exc_val);
1407 return NULL;
1408 }
1409 return res;
1410 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001411#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001412 /* Tcl is not threaded, or this is the interpreter thread. */
1413 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001414}
1415
Guido van Rossum18468821994-06-20 07:49:28 +00001416static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001417SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001418{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001419 char *name1, *name2;
1420 PyObject *newValue;
1421 PyObject *res = NULL;
1422 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001423
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001424 if (PyArg_ParseTuple(args, "O&O:setvar",
1425 varname_converter, &name1, &newValue)) {
1426 /* XXX Acquire tcl lock??? */
1427 newval = AsObj(newValue);
1428 if (newval == NULL)
1429 return NULL;
1430 ENTER_TCL
1431 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1432 newval, flags);
1433 ENTER_OVERLAP
1434 if (!ok)
1435 Tkinter_Error(self);
1436 else {
1437 res = Py_None;
1438 Py_INCREF(res);
1439 }
1440 LEAVE_OVERLAP_TCL
1441 }
1442 else {
1443 PyErr_Clear();
1444 if (PyArg_ParseTuple(args, "ssO:setvar",
1445 &name1, &name2, &newValue)) {
1446 /* XXX must hold tcl lock already??? */
1447 newval = AsObj(newValue);
1448 ENTER_TCL
1449 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1450 ENTER_OVERLAP
1451 if (!ok)
1452 Tkinter_Error(self);
1453 else {
1454 res = Py_None;
1455 Py_INCREF(res);
1456 }
1457 LEAVE_OVERLAP_TCL
1458 }
1459 else {
1460 return NULL;
1461 }
1462 }
1463 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001464}
1465
1466static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001467Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001468{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001469 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001470}
1471
1472static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001473Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001474{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001475 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001476}
1477
Barry Warsawfa701a81997-01-16 00:15:11 +00001478
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001479
Guido van Rossum18468821994-06-20 07:49:28 +00001480static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001481GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001482{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001483 char *name1, *name2=NULL;
1484 PyObject *res = NULL;
1485 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001487 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1488 varname_converter, &name1, &name2))
1489 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001490
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001491 ENTER_TCL
1492 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1493 ENTER_OVERLAP
1494 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001495 PyErr_SetString(Tkinter_TclError,
1496 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001497 } else {
1498 if (((TkappObject*)self)->wantobjects) {
1499 res = FromObj(self, tres);
1500 }
1501 else {
1502 res = PyUnicode_FromString(Tcl_GetString(tres));
1503 }
1504 }
1505 LEAVE_OVERLAP_TCL
1506 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001507}
1508
1509static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001510Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001511{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001512 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001513}
1514
1515static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001516Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001517{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001518 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001519}
1520
Barry Warsawfa701a81997-01-16 00:15:11 +00001521
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001522
Guido van Rossum18468821994-06-20 07:49:28 +00001523static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001524UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001525{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001526 char *name1, *name2=NULL;
1527 int code;
1528 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001529
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001530 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1531 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001532
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 ENTER_TCL
1534 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1535 ENTER_OVERLAP
1536 if (code == TCL_ERROR)
1537 res = Tkinter_Error(self);
1538 else {
1539 Py_INCREF(Py_None);
1540 res = Py_None;
1541 }
1542 LEAVE_OVERLAP_TCL
1543 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001544}
1545
1546static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001547Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001548{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001549 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001550}
1551
1552static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001553Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001554{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001555 return var_invoke(UnsetVar, self, args,
1556 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 +00001561/** Tcl to Python **/
1562
1563static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001564Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001565{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566 char *s;
1567 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001568
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001569 if (PyTuple_Size(args) == 1) {
1570 PyObject* o = PyTuple_GetItem(args, 0);
1571 if (PyLong_Check(o)) {
1572 Py_INCREF(o);
1573 return o;
1574 }
1575 }
1576 if (!PyArg_ParseTuple(args, "s:getint", &s))
1577 return NULL;
1578 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1579 return Tkinter_Error(self);
1580 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001581}
1582
1583static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001584Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001585{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001586 char *s;
1587 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001588
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001589 if (PyTuple_Size(args) == 1) {
1590 PyObject *o = PyTuple_GetItem(args, 0);
1591 if (PyFloat_Check(o)) {
1592 Py_INCREF(o);
1593 return o;
1594 }
1595 }
1596 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1597 return NULL;
1598 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1599 return Tkinter_Error(self);
1600 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001601}
1602
1603static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001604Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001605{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001606 char *s;
1607 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001608
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001609 if (PyTuple_Size(args) == 1) {
1610 PyObject *o = PyTuple_GetItem(args, 0);
1611 if (PyLong_Check(o)) {
1612 Py_INCREF(o);
1613 return o;
1614 }
1615 }
1616 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1617 return NULL;
1618 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1619 return Tkinter_Error(self);
1620 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001621}
1622
1623static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001624Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001625{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001626 char *s;
1627 PyObject *res = NULL;
1628 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001629
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001630 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1631 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001633 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001634
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001635 ENTER_TCL
1636 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1637 ENTER_OVERLAP
1638 if (retval == TCL_ERROR)
1639 res = Tkinter_Error(self);
1640 else
1641 res = Py_BuildValue("s", Tkapp_Result(self));
1642 LEAVE_OVERLAP_TCL
1643 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001644}
1645
1646static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001647Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001648{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001649 char *s;
1650 PyObject *res = NULL;
1651 int retval;
1652 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001654 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1655 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001656
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001657 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001659 ENTER_TCL
1660 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1661 ENTER_OVERLAP
1662 if (retval == TCL_ERROR)
1663 res = Tkinter_Error(self);
1664 else
1665 res = Py_BuildValue("l", v);
1666 LEAVE_OVERLAP_TCL
1667 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001668}
1669
1670static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001671Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001672{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001673 char *s;
1674 PyObject *res = NULL;
1675 double v;
1676 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001677
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001678 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1679 return NULL;
1680 CHECK_TCL_APPARTMENT;
1681 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1682 ENTER_TCL
1683 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1684 ENTER_OVERLAP
1685 PyFPE_END_PROTECT(retval)
1686 if (retval == TCL_ERROR)
1687 res = Tkinter_Error(self);
1688 else
1689 res = Py_BuildValue("d", v);
1690 LEAVE_OVERLAP_TCL
1691 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001692}
1693
1694static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001695Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001696{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001697 char *s;
1698 PyObject *res = NULL;
1699 int retval;
1700 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001702 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1703 return NULL;
1704 CHECK_TCL_APPARTMENT;
1705 ENTER_TCL
1706 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1707 ENTER_OVERLAP
1708 if (retval == TCL_ERROR)
1709 res = Tkinter_Error(self);
1710 else
1711 res = Py_BuildValue("i", v);
1712 LEAVE_OVERLAP_TCL
1713 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001714}
1715
Barry Warsawfa701a81997-01-16 00:15:11 +00001716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001717
Guido van Rossum18468821994-06-20 07:49:28 +00001718static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001719Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001720{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001721 char *list;
1722 int argc;
1723 char **argv;
1724 PyObject *v;
1725 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001726
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001727 if (PyTuple_Size(args) == 1) {
1728 v = PyTuple_GetItem(args, 0);
1729 if (PyTuple_Check(v)) {
1730 Py_INCREF(v);
1731 return v;
1732 }
1733 }
1734 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1735 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001736
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001737 if (Tcl_SplitList(Tkapp_Interp(self), list,
1738 &argc, &argv) == TCL_ERROR) {
1739 PyMem_Free(list);
1740 return Tkinter_Error(self);
1741 }
Guido van Rossum18468821994-06-20 07:49:28 +00001742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001743 if (!(v = PyTuple_New(argc)))
1744 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001745
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001746 for (i = 0; i < argc; i++) {
1747 PyObject *s = PyUnicode_FromString(argv[i]);
1748 if (!s || PyTuple_SetItem(v, i, s)) {
1749 Py_DECREF(v);
1750 v = NULL;
1751 goto finally;
1752 }
1753 }
Guido van Rossum18468821994-06-20 07:49:28 +00001754
Barry Warsawfa701a81997-01-16 00:15:11 +00001755 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001756 ckfree(FREECAST argv);
1757 PyMem_Free(list);
1758 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001759}
1760
1761static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001762Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001763{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001764 PyObject *v;
1765 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001766
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001767 if (PyTuple_Size(args) == 1) {
1768 PyObject* o = PyTuple_GetItem(args, 0);
1769 if (PyTuple_Check(o)) {
1770 o = SplitObj(o);
1771 return o;
1772 }
1773 }
1774 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1775 return NULL;
1776 v = Split(list);
1777 PyMem_Free(list);
1778 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001779}
1780
Barry Warsawfa701a81997-01-16 00:15:11 +00001781
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001782
Guido van Rossum18468821994-06-20 07:49:28 +00001783/** Tcl Command **/
1784
Guido van Rossum00d93061998-05-28 23:06:38 +00001785/* Client data struct */
1786typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001787 PyObject *self;
1788 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001789} PythonCmd_ClientData;
1790
1791static int
Fred Drake509d79a2000-07-08 04:04:38 +00001792PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001793{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001794 errorInCmd = 1;
1795 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1796 LEAVE_PYTHON
1797 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001798}
1799
Guido van Rossum18468821994-06-20 07:49:28 +00001800/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001801 * function or method.
1802 */
Guido van Rossum18468821994-06-20 07:49:28 +00001803static int
Fred Drake509d79a2000-07-08 04:04:38 +00001804PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001805{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001806 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001807 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001808 int i, rv;
1809 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001810
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001811 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001812
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001813 /* TBD: no error checking here since we know, via the
1814 * Tkapp_CreateCommand() that the client data is a two-tuple
1815 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001816 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001817
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001818 /* Create argument list (argv1, ..., argvN) */
1819 if (!(arg = PyTuple_New(argc - 1)))
1820 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001821
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001822 for (i = 0; i < (argc - 1); i++) {
1823 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04001824 if (!s) {
1825 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
1826 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
1827 !strcmp(argv[i + 1], "\xC0\x80")) {
1828 PyErr_Clear();
1829 /* Convert to "strict" utf-8 null */
1830 s = PyUnicode_FromString("\0");
1831 } else {
1832 Py_DECREF(arg);
1833 return PythonCmd_Error(interp);
1834 }
1835 }
1836 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001837 Py_DECREF(arg);
1838 return PythonCmd_Error(interp);
1839 }
1840 }
1841 res = PyEval_CallObject(func, arg);
1842 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001844 if (res == NULL)
1845 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001846
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001847 obj_res = AsObj(res);
1848 if (obj_res == NULL) {
1849 Py_DECREF(res);
1850 return PythonCmd_Error(interp);
1851 }
1852 else {
1853 Tcl_SetObjResult(interp, obj_res);
1854 rv = TCL_OK;
1855 }
Guido van Rossum2834b972000-10-06 16:58:26 +00001856
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001857 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001858
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001859 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001860
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001861 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001862}
1863
1864static void
Fred Drake509d79a2000-07-08 04:04:38 +00001865PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001866{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001867 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00001868
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001869 ENTER_PYTHON
1870 Py_XDECREF(data->self);
1871 Py_XDECREF(data->func);
1872 PyMem_DEL(data);
1873 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001874}
1875
Barry Warsawfa701a81997-01-16 00:15:11 +00001876
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001877
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001878
Benjamin Peterson5879d412009-03-30 14:51:56 +00001879#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001880TCL_DECLARE_MUTEX(command_mutex)
1881
1882typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001883 Tcl_Event ev;
1884 Tcl_Interp* interp;
1885 char *name;
1886 int create;
1887 int *status;
1888 ClientData *data;
1889 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001890} CommandEvent;
1891
1892static int
1893Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001894{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001895 if (ev->create)
1896 *ev->status = Tcl_CreateCommand(
1897 ev->interp, ev->name, PythonCmd,
1898 ev->data, PythonCmdDelete) == NULL;
1899 else
1900 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1901 Tcl_MutexLock(&command_mutex);
1902 Tcl_ConditionNotify(ev->done);
1903 Tcl_MutexUnlock(&command_mutex);
1904 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001905}
Benjamin Peterson5879d412009-03-30 14:51:56 +00001906#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001907
1908static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001909Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001910{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001911 TkappObject *self = (TkappObject*)selfptr;
1912 PythonCmd_ClientData *data;
1913 char *cmdName;
1914 PyObject *func;
1915 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001916
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001917 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
1918 return NULL;
1919 if (!PyCallable_Check(func)) {
1920 PyErr_SetString(PyExc_TypeError, "command not callable");
1921 return NULL;
1922 }
Guido van Rossum18468821994-06-20 07:49:28 +00001923
Martin v. Löwisa9656492003-03-30 08:44:58 +00001924#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001925 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
1926 !WaitForMainloop(self))
1927 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001928#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001929
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001930 data = PyMem_NEW(PythonCmd_ClientData, 1);
1931 if (!data)
1932 return PyErr_NoMemory();
1933 Py_INCREF(self);
1934 Py_INCREF(func);
1935 data->self = selfptr;
1936 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001937#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001938 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1939 Tcl_Condition cond = NULL;
1940 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
1941 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
1942 ev->interp = self->interp;
1943 ev->create = 1;
1944 ev->name = cmdName;
1945 ev->data = (ClientData)data;
1946 ev->status = &err;
1947 ev->done = &cond;
1948 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
1949 Tcl_ConditionFinalize(&cond);
1950 }
1951 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00001952#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001953 {
1954 ENTER_TCL
1955 err = Tcl_CreateCommand(
1956 Tkapp_Interp(self), cmdName, PythonCmd,
1957 (ClientData)data, PythonCmdDelete) == NULL;
1958 LEAVE_TCL
1959 }
1960 if (err) {
1961 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
1962 PyMem_DEL(data);
1963 return NULL;
1964 }
Guido van Rossum18468821994-06-20 07:49:28 +00001965
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001966 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001967}
1968
Barry Warsawfa701a81997-01-16 00:15:11 +00001969
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001970
Guido van Rossum18468821994-06-20 07:49:28 +00001971static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001972Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001973{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001974 TkappObject *self = (TkappObject*)selfptr;
1975 char *cmdName;
1976 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001977
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001978 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
1979 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001980
1981#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001982 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1983 Tcl_Condition cond = NULL;
1984 CommandEvent *ev;
1985 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
1986 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
1987 ev->interp = self->interp;
1988 ev->create = 0;
1989 ev->name = cmdName;
1990 ev->status = &err;
1991 ev->done = &cond;
1992 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
1993 &command_mutex);
1994 Tcl_ConditionFinalize(&cond);
1995 }
1996 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00001997#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001998 {
1999 ENTER_TCL
2000 err = Tcl_DeleteCommand(self->interp, cmdName);
2001 LEAVE_TCL
2002 }
2003 if (err == -1) {
2004 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2005 return NULL;
2006 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002007 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002008}
2009
Barry Warsawfa701a81997-01-16 00:15:11 +00002010
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002011
Guido van Rossum00d93061998-05-28 23:06:38 +00002012#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002013/** File Handler **/
2014
Guido van Rossum00d93061998-05-28 23:06:38 +00002015typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002016 PyObject *func;
2017 PyObject *file;
2018 int id;
2019 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002020} FileHandler_ClientData;
2021
2022static FileHandler_ClientData *HeadFHCD;
2023
2024static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002025NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002026{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002027 FileHandler_ClientData *p;
2028 p = PyMem_NEW(FileHandler_ClientData, 1);
2029 if (p != NULL) {
2030 Py_XINCREF(func);
2031 Py_XINCREF(file);
2032 p->func = func;
2033 p->file = file;
2034 p->id = id;
2035 p->next = HeadFHCD;
2036 HeadFHCD = p;
2037 }
2038 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002039}
2040
2041static void
Fred Drake509d79a2000-07-08 04:04:38 +00002042DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002043{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002044 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002045
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002046 pp = &HeadFHCD;
2047 while ((p = *pp) != NULL) {
2048 if (p->id == id) {
2049 *pp = p->next;
2050 Py_XDECREF(p->func);
2051 Py_XDECREF(p->file);
2052 PyMem_DEL(p);
2053 }
2054 else
2055 pp = &p->next;
2056 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002057}
2058
Guido van Rossuma597dde1995-01-10 20:56:29 +00002059static void
Fred Drake509d79a2000-07-08 04:04:38 +00002060FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002061{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002062 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2063 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002065 ENTER_PYTHON
2066 func = data->func;
2067 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002068
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002069 arg = Py_BuildValue("(Oi)", file, (long) mask);
2070 res = PyEval_CallObject(func, arg);
2071 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002072
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002073 if (res == NULL) {
2074 errorInCmd = 1;
2075 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2076 }
2077 Py_XDECREF(res);
2078 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002079}
2080
Guido van Rossum18468821994-06-20 07:49:28 +00002081static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002082Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2083 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002084{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002085 FileHandler_ClientData *data;
2086 PyObject *file, *func;
2087 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002088
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002089 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2090 &file, &mask, &func))
2091 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002092
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002093 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002094
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002095 tfile = PyObject_AsFileDescriptor(file);
2096 if (tfile < 0)
2097 return NULL;
2098 if (!PyCallable_Check(func)) {
2099 PyErr_SetString(PyExc_TypeError, "bad argument list");
2100 return NULL;
2101 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002102
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002103 data = NewFHCD(func, file, tfile);
2104 if (data == NULL)
2105 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002106
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002107 /* Ought to check for null Tcl_File object... */
2108 ENTER_TCL
2109 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2110 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002111 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002112}
2113
2114static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002115Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002116{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002117 PyObject *file;
2118 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002119
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002120 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2121 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002122
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002123 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002124
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002125 tfile = PyObject_AsFileDescriptor(file);
2126 if (tfile < 0)
2127 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002128
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002129 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002130
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002131 /* Ought to check for null Tcl_File object... */
2132 ENTER_TCL
2133 Tcl_DeleteFileHandler(tfile);
2134 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002135 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002136}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002137#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002138
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002139
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002140/**** Tktt Object (timer token) ****/
2141
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002142static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002143
Guido van Rossum00d93061998-05-28 23:06:38 +00002144typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002145 PyObject_HEAD
2146 Tcl_TimerToken token;
2147 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002148} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002149
2150static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002151Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002152{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002153 TkttObject *v = (TkttObject *)self;
2154 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002155
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002156 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2157 return NULL;
2158 if (v->token != NULL) {
2159 Tcl_DeleteTimerHandler(v->token);
2160 v->token = NULL;
2161 }
2162 if (func != NULL) {
2163 v->func = NULL;
2164 Py_DECREF(func);
2165 Py_DECREF(v); /* See Tktt_New() */
2166 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002167 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002168}
2169
2170static PyMethodDef Tktt_methods[] =
2171{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002172 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2173 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002174};
2175
2176static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002177Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002178{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002179 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002180
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002181 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002182 if (v == NULL)
2183 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002184
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002185 Py_INCREF(func);
2186 v->token = NULL;
2187 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002188
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002189 /* Extra reference, deleted when called or when handler is deleted */
2190 Py_INCREF(v);
2191 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002192}
2193
2194static void
Fred Drake509d79a2000-07-08 04:04:38 +00002195Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002196{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 TkttObject *v = (TkttObject *)self;
2198 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002199
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002200 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002201
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002202 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002203}
2204
Guido van Rossum597ac201998-05-12 14:36:19 +00002205static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002206Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002207{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002208 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002209 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2210 v,
2211 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002212}
2213
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002214static PyType_Slot Tktt_Type_slots[] = {
2215 {Py_tp_dealloc, Tktt_Dealloc},
2216 {Py_tp_repr, Tktt_Repr},
2217 {Py_tp_methods, Tktt_methods},
2218 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002219};
2220
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002221static PyType_Spec Tktt_Type_spec = {
2222 "tktimertoken",
2223 sizeof(TkttObject),
2224 0,
2225 Py_TPFLAGS_DEFAULT,
2226 Tktt_Type_slots,
2227};
Barry Warsawfa701a81997-01-16 00:15:11 +00002228
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002229
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002230/** Timer Handler **/
2231
2232static void
Fred Drake509d79a2000-07-08 04:04:38 +00002233TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002234{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002235 TkttObject *v = (TkttObject *)clientData;
2236 PyObject *func = v->func;
2237 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002239 if (func == NULL)
2240 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002241
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002242 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002243
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002244 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002245
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002246 res = PyEval_CallObject(func, NULL);
2247 Py_DECREF(func);
2248 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002249
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002250 if (res == NULL) {
2251 errorInCmd = 1;
2252 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2253 }
2254 else
2255 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002257 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002258}
2259
2260static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002261Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002262{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002263 int milliseconds;
2264 PyObject *func;
2265 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002266
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002267 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2268 &milliseconds, &func))
2269 return NULL;
2270 if (!PyCallable_Check(func)) {
2271 PyErr_SetString(PyExc_TypeError, "bad argument list");
2272 return NULL;
2273 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002275 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002276
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002277 v = Tktt_New(func);
2278 if (v) {
2279 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2280 (ClientData)v);
2281 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002282
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002283 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002284}
2285
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002286
Guido van Rossum18468821994-06-20 07:49:28 +00002287/** Event Loop **/
2288
Guido van Rossum18468821994-06-20 07:49:28 +00002289static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002290Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002291{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002292 int threshold = 0;
2293 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002294#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002295 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002296#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002298 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2299 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002300
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002301 CHECK_TCL_APPARTMENT;
2302 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002303
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002304 quitMainLoop = 0;
2305 while (Tk_GetNumMainWindows() > threshold &&
2306 !quitMainLoop &&
2307 !errorInCmd)
2308 {
2309 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002310
2311#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002312 if (self->threaded) {
2313 /* Allow other Python threads to run. */
2314 ENTER_TCL
2315 result = Tcl_DoOneEvent(0);
2316 LEAVE_TCL
2317 }
2318 else {
2319 Py_BEGIN_ALLOW_THREADS
2320 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2321 tcl_tstate = tstate;
2322 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2323 tcl_tstate = NULL;
2324 if(tcl_lock)PyThread_release_lock(tcl_lock);
2325 if (result == 0)
2326 Sleep(Tkinter_busywaitinterval);
2327 Py_END_ALLOW_THREADS
2328 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002329#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002330 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002331#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002332
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002333 if (PyErr_CheckSignals() != 0) {
2334 self->dispatching = 0;
2335 return NULL;
2336 }
2337 if (result < 0)
2338 break;
2339 }
2340 self->dispatching = 0;
2341 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002343 if (errorInCmd) {
2344 errorInCmd = 0;
2345 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2346 excInCmd = valInCmd = trbInCmd = NULL;
2347 return NULL;
2348 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002349 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002350}
2351
2352static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002353Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002354{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002355 int flags = 0;
2356 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002357
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002358 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2359 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002361 ENTER_TCL
2362 rv = Tcl_DoOneEvent(flags);
2363 LEAVE_TCL
2364 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002365}
2366
2367static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002368Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002369{
2370
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002371 if (!PyArg_ParseTuple(args, ":quit"))
2372 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002373
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002374 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002375 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002376}
2377
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002378static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002379Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002380{
2381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002382 if (!PyArg_ParseTuple(args, ":interpaddr"))
2383 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002384
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002385 return PyLong_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002386}
2387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002388static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002389Tkapp_TkInit(PyObject *self, PyObject *args)
2390{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002391 Tcl_Interp *interp = Tkapp_Interp(self);
2392 const char * _tk_exists = NULL;
2393 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002394
Guilherme Polob681df42009-02-09 22:33:59 +00002395#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002396 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2397 * first call failed.
2398 * To avoid the deadlock, we just refuse the second call through
2399 * a static variable.
2400 */
2401 if (tk_load_failed) {
2402 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2403 return NULL;
2404 }
Guilherme Polob681df42009-02-09 22:33:59 +00002405#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 /* We want to guard against calling Tk_Init() multiple times */
2408 CHECK_TCL_APPARTMENT;
2409 ENTER_TCL
2410 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2411 ENTER_OVERLAP
2412 if (err == TCL_ERROR) {
2413 /* This sets an exception, but we cannot return right
2414 away because we need to exit the overlap first. */
2415 Tkinter_Error(self);
2416 } else {
2417 _tk_exists = Tkapp_Result(self);
2418 }
2419 LEAVE_OVERLAP_TCL
2420 if (err == TCL_ERROR) {
2421 return NULL;
2422 }
2423 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2424 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002425 PyErr_SetString(Tkinter_TclError,
2426 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002427#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002428 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002429#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002430 return NULL;
2431 }
2432 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002433 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002434}
Barry Warsawfa701a81997-01-16 00:15:11 +00002435
Martin v. Löwisffad6332002-11-26 09:28:05 +00002436static PyObject *
2437Tkapp_WantObjects(PyObject *self, PyObject *args)
2438{
2439
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002440 int wantobjects = -1;
2441 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2442 return NULL;
2443 if (wantobjects == -1)
2444 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2445 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002446
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002447 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002448}
2449
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002450static PyObject *
2451Tkapp_WillDispatch(PyObject *self, PyObject *args)
2452{
2453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002454 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002455
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002456 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002457}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002459
Guido van Rossum18468821994-06-20 07:49:28 +00002460/**** Tkapp Method List ****/
2461
2462static PyMethodDef Tkapp_methods[] =
2463{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002464 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2465 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2466 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002467 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002468 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2469 {"record", Tkapp_Record, METH_VARARGS},
2470 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2471 {"setvar", Tkapp_SetVar, METH_VARARGS},
2472 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2473 {"getvar", Tkapp_GetVar, METH_VARARGS},
2474 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2475 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2476 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2477 {"getint", Tkapp_GetInt, METH_VARARGS},
2478 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2479 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2480 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2481 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2482 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2483 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2484 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2485 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002486 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2487 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002488#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002489 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2490 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002491#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002492 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2493 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2494 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2495 {"quit", Tkapp_Quit, METH_VARARGS},
2496 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2497 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2498 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002499};
2500
Barry Warsawfa701a81997-01-16 00:15:11 +00002501
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002502
Guido van Rossum18468821994-06-20 07:49:28 +00002503/**** Tkapp Type Methods ****/
2504
2505static void
Fred Drake509d79a2000-07-08 04:04:38 +00002506Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002507{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 /*CHECK_TCL_APPARTMENT;*/
2509 ENTER_TCL
2510 Tcl_DeleteInterp(Tkapp_Interp(self));
2511 LEAVE_TCL
2512 PyObject_Del(self);
2513 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002514}
2515
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002516static PyType_Slot Tkapp_Type_slots[] = {
2517 {Py_tp_dealloc, Tkapp_Dealloc},
2518 {Py_tp_methods, Tkapp_methods},
2519 {0, 0}
2520};
2521
2522
2523static PyType_Spec Tkapp_Type_spec = {
2524 "tkapp",
2525 sizeof(TkappObject),
2526 0,
2527 Py_TPFLAGS_DEFAULT,
2528 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002529};
2530
Barry Warsawfa701a81997-01-16 00:15:11 +00002531
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002532
Guido van Rossum18468821994-06-20 07:49:28 +00002533/**** Tkinter Module ****/
2534
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002535typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002536 PyObject* tuple;
2537 int size; /* current size */
2538 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002539} FlattenContext;
2540
2541static int
2542_bump(FlattenContext* context, int size)
2543{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002544 /* expand tuple to hold (at least) size new items.
2545 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002546
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002547 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002548
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002549 if (maxsize < context->size + size)
2550 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002551
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002552 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002553
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002554 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002555}
2556
2557static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002558_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002559{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002561
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002562 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002564 if (depth > 1000) {
2565 PyErr_SetString(PyExc_ValueError,
2566 "nesting too deep in _flatten");
2567 return 0;
2568 } else if (PyList_Check(item)) {
2569 size = PyList_GET_SIZE(item);
2570 /* preallocate (assume no nesting) */
2571 if (context->size + size > context->maxsize &&
2572 !_bump(context, size))
2573 return 0;
2574 /* copy items to output tuple */
2575 for (i = 0; i < size; i++) {
2576 PyObject *o = PyList_GET_ITEM(item, i);
2577 if (PyList_Check(o) || PyTuple_Check(o)) {
2578 if (!_flatten1(context, o, depth + 1))
2579 return 0;
2580 } else if (o != Py_None) {
2581 if (context->size + 1 > context->maxsize &&
2582 !_bump(context, 1))
2583 return 0;
2584 Py_INCREF(o);
2585 PyTuple_SET_ITEM(context->tuple,
2586 context->size++, o);
2587 }
2588 }
2589 } else if (PyTuple_Check(item)) {
2590 /* same, for tuples */
2591 size = PyTuple_GET_SIZE(item);
2592 if (context->size + size > context->maxsize &&
2593 !_bump(context, size))
2594 return 0;
2595 for (i = 0; i < size; i++) {
2596 PyObject *o = PyTuple_GET_ITEM(item, i);
2597 if (PyList_Check(o) || PyTuple_Check(o)) {
2598 if (!_flatten1(context, o, depth + 1))
2599 return 0;
2600 } else if (o != Py_None) {
2601 if (context->size + 1 > context->maxsize &&
2602 !_bump(context, 1))
2603 return 0;
2604 Py_INCREF(o);
2605 PyTuple_SET_ITEM(context->tuple,
2606 context->size++, o);
2607 }
2608 }
2609 } else {
2610 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2611 return 0;
2612 }
2613 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002614}
2615
2616static PyObject *
2617Tkinter_Flatten(PyObject* self, PyObject* args)
2618{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002619 FlattenContext context;
2620 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002621
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002622 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2623 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002625 context.maxsize = PySequence_Size(item);
2626 if (context.maxsize < 0)
2627 return NULL;
2628 if (context.maxsize == 0)
2629 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002631 context.tuple = PyTuple_New(context.maxsize);
2632 if (!context.tuple)
2633 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002634
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002635 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002637 if (!_flatten1(&context, item,0))
2638 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002639
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002640 if (_PyTuple_Resize(&context.tuple, context.size))
2641 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002643 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002644}
2645
Guido van Rossum18468821994-06-20 07:49:28 +00002646static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002647Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002648{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002649 char *screenName = NULL;
2650 char *baseName = NULL; /* XXX this is not used anymore;
2651 try getting rid of it. */
2652 char *className = NULL;
2653 int interactive = 0;
2654 int wantobjects = 0;
2655 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2656 int sync = 0; /* pass -sync to wish */
2657 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002659 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002661 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2662 &screenName, &baseName, &className,
2663 &interactive, &wantobjects, &wantTk,
2664 &sync, &use))
2665 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002667 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002668 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002669 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002670}
2671
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002672static PyObject *
2673Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2674{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002675 int new_val;
2676 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2677 return NULL;
2678 if (new_val < 0) {
2679 PyErr_SetString(PyExc_ValueError,
2680 "busywaitinterval must be >= 0");
2681 return NULL;
2682 }
2683 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002684 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002685}
2686
2687static char setbusywaitinterval_doc[] =
2688"setbusywaitinterval(n) -> None\n\
2689\n\
2690Set the busy-wait interval in milliseconds between successive\n\
2691calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2692It should be set to a divisor of the maximum time between\n\
2693frames in an animation.";
2694
2695static PyObject *
2696Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2697{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002698 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002699}
2700
2701static char getbusywaitinterval_doc[] =
2702"getbusywaitinterval() -> int\n\
2703\n\
2704Return the current busy-wait interval between successive\n\
2705calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2706
Guido van Rossum18468821994-06-20 07:49:28 +00002707static PyMethodDef moduleMethods[] =
2708{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002709 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2710 {"create", Tkinter_Create, METH_VARARGS},
2711 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2712 setbusywaitinterval_doc},
2713 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2714 METH_NOARGS, getbusywaitinterval_doc},
2715 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002716};
2717
Guido van Rossum7bf15641998-05-22 18:28:17 +00002718#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002719
2720static int stdin_ready = 0;
2721
Guido van Rossumad4db171998-06-13 13:56:28 +00002722#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002723static void
Fred Drake509d79a2000-07-08 04:04:38 +00002724MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002725{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002726 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002727}
Guido van Rossumad4db171998-06-13 13:56:28 +00002728#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002729
Martin v. Löwisa9656492003-03-30 08:44:58 +00002730#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002731static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002732#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002733
Guido van Rossum18468821994-06-20 07:49:28 +00002734static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002735EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002736{
Guido van Rossumad4db171998-06-13 13:56:28 +00002737#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002738 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002739#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002740#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002742#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002743 stdin_ready = 0;
2744 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002745#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002746 tfile = fileno(stdin);
2747 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002748#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002749 while (!errorInCmd && !stdin_ready) {
2750 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002751#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002752 if (_kbhit()) {
2753 stdin_ready = 1;
2754 break;
2755 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002756#endif
2757#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002758 Py_BEGIN_ALLOW_THREADS
2759 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2760 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002761
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002762 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002763
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002764 tcl_tstate = NULL;
2765 if(tcl_lock)PyThread_release_lock(tcl_lock);
2766 if (result == 0)
2767 Sleep(Tkinter_busywaitinterval);
2768 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002769#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002770 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002771#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002772
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002773 if (result < 0)
2774 break;
2775 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002776#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002777 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002778#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002779 if (errorInCmd) {
2780 errorInCmd = 0;
2781 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2782 excInCmd = valInCmd = trbInCmd = NULL;
2783 PyErr_Print();
2784 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002785#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002786 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002787#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002788 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002789}
Guido van Rossum18468821994-06-20 07:49:28 +00002790
Guido van Rossum00d93061998-05-28 23:06:38 +00002791#endif
2792
Guido van Rossum7bf15641998-05-22 18:28:17 +00002793static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002794EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002795{
Guido van Rossum00d93061998-05-28 23:06:38 +00002796#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002797 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002798#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002799 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002800#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002801 PyOS_InputHook = EventHook;
2802 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002803#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002804}
2805
2806static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002807DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002808{
Guido van Rossum00d93061998-05-28 23:06:38 +00002809#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002810 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2811 PyOS_InputHook = NULL;
2812 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002813#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002814}
2815
Barry Warsawfa701a81997-01-16 00:15:11 +00002816
Martin v. Löwis1a214512008-06-11 05:26:20 +00002817static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002818 PyModuleDef_HEAD_INIT,
2819 "_tkinter",
2820 NULL,
2821 -1,
2822 moduleMethods,
2823 NULL,
2824 NULL,
2825 NULL,
2826 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002827};
2828
Mark Hammond62b1ab12002-07-23 06:31:15 +00002829PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002830PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002831{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002832 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00002833
Guido van Rossum00d93061998-05-28 23:06:38 +00002834#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002835 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002836 if (tcl_lock == NULL)
2837 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002838#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002839
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002840 m = PyModule_Create(&_tkintermodule);
2841 if (m == NULL)
2842 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002843
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002844 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
2845 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02002846 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002847 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02002848 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002849 Py_INCREF(o);
2850 if (PyModule_AddObject(m, "TclError", o)) {
2851 Py_DECREF(o);
2852 Py_DECREF(m);
2853 return NULL;
2854 }
2855 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002856
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002857 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
2858 Py_DECREF(m);
2859 return NULL;
2860 }
2861 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
2862 Py_DECREF(m);
2863 return NULL;
2864 }
2865 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
2866 Py_DECREF(m);
2867 return NULL;
2868 }
2869 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
2870 Py_DECREF(m);
2871 return NULL;
2872 }
2873 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
2874 Py_DECREF(m);
2875 return NULL;
2876 }
2877 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
2878 Py_DECREF(m);
2879 return NULL;
2880 }
2881 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
2882 Py_DECREF(m);
2883 return NULL;
2884 }
2885 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
2886 Py_DECREF(m);
2887 return NULL;
2888 }
2889 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
2890 Py_DECREF(m);
2891 return NULL;
2892 }
2893 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
2894 Py_DECREF(m);
2895 return NULL;
2896 }
2897 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
2898 Py_DECREF(m);
2899 return NULL;
2900 }
2901
2902 o = PyType_FromSpec(&Tkapp_Type_spec);
2903 if (o == NULL) {
2904 Py_DECREF(m);
2905 return NULL;
2906 }
2907 if (PyModule_AddObject(m, "TkappType", o)) {
2908 Py_DECREF(o);
2909 Py_DECREF(m);
2910 return NULL;
2911 }
2912 Tkapp_Type = o;
2913
2914 o = PyType_FromSpec(&Tktt_Type_spec);
2915 if (o == NULL) {
2916 Py_DECREF(m);
2917 return NULL;
2918 }
2919 if (PyModule_AddObject(m, "TkttType", o)) {
2920 Py_DECREF(o);
2921 Py_DECREF(m);
2922 return NULL;
2923 }
2924 Tktt_Type = o;
2925
2926 o = PyType_FromSpec(&PyTclObject_Type_spec);
2927 if (o == NULL) {
2928 Py_DECREF(m);
2929 return NULL;
2930 }
2931 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
2932 Py_DECREF(o);
2933 Py_DECREF(m);
2934 return NULL;
2935 }
2936 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00002937
2938#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002939 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2940 * start waking up. Note that Tcl_FindExecutable will do this, this
2941 * code must be above it! The original warning from
2942 * tkMacOSXAppInit.c is copied below.
2943 *
2944 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2945 * Tcl interpreter for now. It probably should work to do this
2946 * in the other order, but for now it doesn't seem to.
2947 *
2948 */
2949 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00002950#endif
2951
2952
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002953 /* This helps the dynamic loader; in Unicode aware Tcl versions
2954 it also helps Tcl find its encodings. */
2955 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
2956 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00002957 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002958 if (cexe)
2959 Tcl_FindExecutable(PyBytes_AsString(cexe));
2960 Py_XDECREF(cexe);
2961 Py_DECREF(uexe);
2962 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00002963
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002964 if (PyErr_Occurred()) {
2965 Py_DECREF(m);
2966 return NULL;
2967 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002968
Guido van Rossum43ff8681998-07-14 18:02:13 +00002969#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002970 /* This was not a good idea; through <Destroy> bindings,
2971 Tcl_Finalize() may invoke Python code but at that point the
2972 interpreter and thread state have already been destroyed! */
2973 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002974#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002975 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00002976}