blob: 637a9bb205d254fa30e12f637e611472af03012b [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 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300426 else if (PyUnicode_Check(arg)) {
427 int argc;
428 char **argv;
429 char *list = PyUnicode_AsUTF8(arg);
430
431 if (list == NULL ||
432 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
433 Py_INCREF(arg);
434 return arg;
435 }
436 Tcl_Free(FREECAST argv);
437 if (argc > 1)
438 return Split(list);
439 /* Fall through, returning arg. */
440 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000441 else if (PyBytes_Check(arg)) {
442 int argc;
443 char **argv;
444 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000445
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000446 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
447 Py_INCREF(arg);
448 return arg;
449 }
450 Tcl_Free(FREECAST argv);
451 if (argc > 1)
452 return Split(PyBytes_AsString(arg));
453 /* Fall through, returning arg. */
454 }
455 Py_INCREF(arg);
456 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000457}
Barry Warsawfa701a81997-01-16 00:15:11 +0000458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000459
Guido van Rossum18468821994-06-20 07:49:28 +0000460/**** Tkapp Object ****/
461
462#ifndef WITH_APPINIT
463int
Fred Drake509d79a2000-07-08 04:04:38 +0000464Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000465{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000467
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000468 if (Tcl_Init(interp) == TCL_ERROR) {
469 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
470 return TCL_ERROR;
471 }
Guilherme Polob681df42009-02-09 22:33:59 +0000472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000473 _tkinter_skip_tk_init = Tcl_GetVar(interp,
474 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
475 if (_tkinter_skip_tk_init != NULL &&
476 strcmp(_tkinter_skip_tk_init, "1") == 0) {
477 return TCL_OK;
478 }
Guilherme Polob681df42009-02-09 22:33:59 +0000479
480#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000481 if (tk_load_failed) {
482 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
483 return TCL_ERROR;
484 }
Guilherme Polob681df42009-02-09 22:33:59 +0000485#endif
486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000487 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000488#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000489 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000490#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000491 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
492 return TCL_ERROR;
493 }
Guilherme Polob681df42009-02-09 22:33:59 +0000494
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000495 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000496}
497#endif /* !WITH_APPINIT */
498
Guido van Rossum18468821994-06-20 07:49:28 +0000499
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000500
Barry Warsawfa701a81997-01-16 00:15:11 +0000501
502/* Initialize the Tk application; see the `main' function in
503 * `tkMain.c'.
504 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000505
Thomas Wouters58d05102000-07-24 14:43:35 +0000506static void EnableEventHook(void); /* Forward */
507static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000508
Barry Warsawfa701a81997-01-16 00:15:11 +0000509static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000510Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000511 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000512{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513 TkappObject *v;
514 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000515
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300516 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000517 if (v == NULL)
518 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200519 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000520
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000521 v->interp = Tcl_CreateInterp();
522 v->wantobjects = wantobjects;
523 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
524 TCL_GLOBAL_ONLY) != NULL;
525 v->thread_id = Tcl_GetCurrentThread();
526 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000527
528#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000529 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300530 PyErr_SetString(PyExc_RuntimeError,
531 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000532 Py_DECREF(v);
533 return 0;
534 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000535#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000536#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000537 if (v->threaded && tcl_lock) {
538 /* If Tcl is threaded, we don't need the lock. */
539 PyThread_free_lock(tcl_lock);
540 tcl_lock = NULL;
541 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000542#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000543
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000544 v->BooleanType = Tcl_GetObjType("boolean");
545 v->ByteArrayType = Tcl_GetObjType("bytearray");
546 v->DoubleType = Tcl_GetObjType("double");
547 v->IntType = Tcl_GetObjType("int");
548 v->ListType = Tcl_GetObjType("list");
549 v->ProcBodyType = Tcl_GetObjType("procbody");
550 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000551
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000552 /* Delete the 'exit' command, which can screw things up */
553 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000554
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000555 if (screenName != NULL)
556 Tcl_SetVar2(v->interp, "env", "DISPLAY",
557 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000558
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000559 if (interactive)
560 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
561 else
562 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000564 /* This is used to get the application class for Tk 4.1 and up */
565 argv0 = (char*)ckalloc(strlen(className) + 1);
566 if (!argv0) {
567 PyErr_NoMemory();
568 Py_DECREF(v);
569 return NULL;
570 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000571
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000572 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200573 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
574 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000575 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
576 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000578 if (! wantTk) {
579 Tcl_SetVar(v->interp,
580 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
581 }
Guilherme Polob681df42009-02-09 22:33:59 +0000582#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000583 else if (tk_load_failed) {
584 Tcl_SetVar(v->interp,
585 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
586 }
Guilherme Polob681df42009-02-09 22:33:59 +0000587#endif
David Aschere2b4b322004-02-18 05:59:53 +0000588
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000589 /* some initial arguments need to be in argv */
590 if (sync || use) {
591 char *args;
592 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000593
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000594 if (sync)
595 len += sizeof "-sync";
596 if (use)
597 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000598
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000599 args = (char*)ckalloc(len);
600 if (!args) {
601 PyErr_NoMemory();
602 Py_DECREF(v);
603 return NULL;
604 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000605
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000606 args[0] = '\0';
607 if (sync)
608 strcat(args, "-sync");
609 if (use) {
610 if (sync)
611 strcat(args, " ");
612 strcat(args, "-use ");
613 strcat(args, use);
614 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000615
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
617 ckfree(args);
618 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000619
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000620 if (Tcl_AppInit(v->interp) != TCL_OK) {
621 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000622#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 if (wantTk) {
624 const char *_tkinter_tk_failed;
625 _tkinter_tk_failed = Tcl_GetVar(v->interp,
626 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000628 if ( _tkinter_tk_failed != NULL &&
629 strcmp(_tkinter_tk_failed, "1") == 0) {
630 tk_load_failed = 1;
631 }
632 }
Guilherme Polob681df42009-02-09 22:33:59 +0000633#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000634 Py_DECREF((PyObject *)v);
635 return (TkappObject *)result;
636 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000637
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000639
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000640 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000641}
642
Barry Warsawfa701a81997-01-16 00:15:11 +0000643
Benjamin Peterson5879d412009-03-30 14:51:56 +0000644#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000645static void
646Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000648{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000649 Py_BEGIN_ALLOW_THREADS;
650 Tcl_MutexLock(mutex);
651 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
652 Tcl_ThreadAlert(self->thread_id);
653 Tcl_ConditionWait(cond, mutex, NULL);
654 Tcl_MutexUnlock(mutex);
655 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000656}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000657#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000659
Guido van Rossum18468821994-06-20 07:49:28 +0000660/** Tcl Eval **/
661
Martin v. Löwisffad6332002-11-26 09:28:05 +0000662typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000663 PyObject_HEAD
664 Tcl_Obj *value;
665 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000666} PyTclObject;
667
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300668static PyObject *PyTclObject_Type;
669#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000670
671static PyObject *
672newPyTclObject(Tcl_Obj *arg)
673{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300675 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 if (self == NULL)
677 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200678 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000679 Tcl_IncrRefCount(arg);
680 self->value = arg;
681 self->string = NULL;
682 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000683}
684
685static void
686PyTclObject_dealloc(PyTclObject *self)
687{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200688 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000689 Tcl_DecrRefCount(self->value);
690 Py_XDECREF(self->string);
691 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200692 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000693}
694
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000695static char*
696PyTclObject_TclString(PyObject *self)
697{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000698 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000699}
700
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000701/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000702PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000703"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000704
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000705static PyObject *
706PyTclObject_string(PyTclObject *self, void *ignored)
707{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000708 char *s;
709 int len;
710 if (!self->string) {
711 s = Tcl_GetStringFromObj(self->value, &len);
712 self->string = PyUnicode_FromStringAndSize(s, len);
713 if (!self->string)
714 return NULL;
715 }
716 Py_INCREF(self->string);
717 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000718}
719
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000720static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000721PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000722{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000723 char *s;
724 int len;
725 if (self->string && PyUnicode_Check(self->string)) {
726 Py_INCREF(self->string);
727 return self->string;
728 }
729 /* XXX Could chache result if it is non-ASCII. */
730 s = Tcl_GetStringFromObj(self->value, &len);
731 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000732}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000733
Martin v. Löwisffad6332002-11-26 09:28:05 +0000734static PyObject *
735PyTclObject_repr(PyTclObject *self)
736{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000737 return PyUnicode_FromFormat("<%s object at %p>",
738 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000739}
740
Mark Dickinson211c6252009-02-01 10:28:51 +0000741#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
742
743static PyObject *
744PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000745{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000746 int result;
747 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 /* neither argument should be NULL, unless something's gone wrong */
750 if (self == NULL || other == NULL) {
751 PyErr_BadInternalCall();
752 return NULL;
753 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000754
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000755 /* both arguments should be instances of PyTclObject */
756 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
757 v = Py_NotImplemented;
758 goto finished;
759 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000760
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000761 if (self == other)
762 /* fast path when self and other are identical */
763 result = 0;
764 else
765 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
766 Tcl_GetString(((PyTclObject *)other)->value));
767 /* Convert return value to a Boolean */
768 switch (op) {
769 case Py_EQ:
770 v = TEST_COND(result == 0);
771 break;
772 case Py_NE:
773 v = TEST_COND(result != 0);
774 break;
775 case Py_LE:
776 v = TEST_COND(result <= 0);
777 break;
778 case Py_GE:
779 v = TEST_COND(result >= 0);
780 break;
781 case Py_LT:
782 v = TEST_COND(result < 0);
783 break;
784 case Py_GT:
785 v = TEST_COND(result > 0);
786 break;
787 default:
788 PyErr_BadArgument();
789 return NULL;
790 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000791 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000792 Py_INCREF(v);
793 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000794}
795
Martin v. Löwis39195712003-01-04 00:33:13 +0000796PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
797
Martin v. Löwisffad6332002-11-26 09:28:05 +0000798static PyObject*
799get_typename(PyTclObject* obj, void* ignored)
800{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000801 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000802}
803
Martin v. Löwis39195712003-01-04 00:33:13 +0000804
Martin v. Löwisffad6332002-11-26 09:28:05 +0000805static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000806 {"typename", (getter)get_typename, NULL, get_typename__doc__},
807 {"string", (getter)PyTclObject_string, NULL,
808 PyTclObject_string__doc__},
809 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000810};
811
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300812static PyType_Slot PyTclObject_Type_slots[] = {
813 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
814 {Py_tp_repr, (reprfunc)PyTclObject_repr},
815 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200816 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300817 {Py_tp_richcompare, PyTclObject_richcompare},
818 {Py_tp_getset, PyTclObject_getsetlist},
819 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000820};
821
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300822static PyType_Spec PyTclObject_Type_spec = {
823 "_tkinter.Tcl_Obj",
824 sizeof(PyTclObject),
825 0,
826 Py_TPFLAGS_DEFAULT,
827 PyTclObject_Type_slots,
828};
829
830
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000831static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000832AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000833{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000834 Tcl_Obj *result;
835 long longVal;
836 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000837
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000838 if (PyBytes_Check(value))
839 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
840 PyBytes_GET_SIZE(value));
841 else if (PyBool_Check(value))
842 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
843 else if (PyLong_CheckExact(value) &&
844 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
845 !overflow)) {
846 /* If there is an overflow in the long conversion,
847 fall through to default object handling. */
848 return Tcl_NewLongObj(longVal);
849 }
850 else if (PyFloat_Check(value))
851 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
852 else if (PyTuple_Check(value)) {
853 Tcl_Obj **argv = (Tcl_Obj**)
854 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
855 int i;
856 if(!argv)
857 return 0;
858 for(i=0;i<PyTuple_Size(value);i++)
859 argv[i] = AsObj(PyTuple_GetItem(value,i));
860 result = Tcl_NewListObj(PyTuple_Size(value), argv);
861 ckfree(FREECAST argv);
862 return result;
863 }
864 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200865 void *inbuf;
866 Py_ssize_t size;
867 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000868 Tcl_UniChar *outbuf = NULL;
869 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200870 size_t allocsize;
871
872 if (PyUnicode_READY(value) == -1)
873 return NULL;
874
875 inbuf = PyUnicode_DATA(value);
876 size = PyUnicode_GET_LENGTH(value);
877 kind = PyUnicode_KIND(value);
878 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
879 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000880 /* Else overflow occurred, and we take the next exit */
881 if (!outbuf) {
882 PyErr_NoMemory();
883 return NULL;
884 }
885 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200886 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
887 /* We cannot test for sizeof(Tcl_UniChar) directly,
888 so we test for UTF-8 size instead. */
889#if TCL_UTF_MAX == 3
890 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000891 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200892 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100893 "character U+%x is above the range "
894 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100895 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000896 ckfree(FREECAST outbuf);
897 return NULL;
898 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300899#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200900 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000901 }
902 result = Tcl_NewUnicodeObj(outbuf, size);
903 ckfree(FREECAST outbuf);
904 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000905 }
906 else if(PyTclObject_Check(value)) {
907 Tcl_Obj *v = ((PyTclObject*)value)->value;
908 Tcl_IncrRefCount(v);
909 return v;
910 }
911 else {
912 PyObject *v = PyObject_Str(value);
913 if (!v)
914 return 0;
915 result = AsObj(v);
916 Py_DECREF(v);
917 return result;
918 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000919}
920
Martin v. Löwisffad6332002-11-26 09:28:05 +0000921static PyObject*
922FromObj(PyObject* tkapp, Tcl_Obj *value)
923{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000924 PyObject *result = NULL;
925 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000926
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000927 if (value->typePtr == NULL) {
928 return PyUnicode_FromStringAndSize(value->bytes,
929 value->length);
930 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000931
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000932 if (value->typePtr == app->BooleanType) {
933 result = value->internalRep.longValue ? Py_True : Py_False;
934 Py_INCREF(result);
935 return result;
936 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000937
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000938 if (value->typePtr == app->ByteArrayType) {
939 int size;
940 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
941 return PyBytes_FromStringAndSize(data, size);
942 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000943
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000944 if (value->typePtr == app->DoubleType) {
945 return PyFloat_FromDouble(value->internalRep.doubleValue);
946 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000947
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000948 if (value->typePtr == app->IntType) {
949 return PyLong_FromLong(value->internalRep.longValue);
950 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000951
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000952 if (value->typePtr == app->ListType) {
953 int size;
954 int i, status;
955 PyObject *elem;
956 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000957
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000958 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
959 if (status == TCL_ERROR)
960 return Tkinter_Error(tkapp);
961 result = PyTuple_New(size);
962 if (!result)
963 return NULL;
964 for (i = 0; i < size; i++) {
965 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
966 value, i, &tcl_elem);
967 if (status == TCL_ERROR) {
968 Py_DECREF(result);
969 return Tkinter_Error(tkapp);
970 }
971 elem = FromObj(tkapp, tcl_elem);
972 if (!elem) {
973 Py_DECREF(result);
974 return NULL;
975 }
976 PyTuple_SetItem(result, i, elem);
977 }
978 return result;
979 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000980
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000981 if (value->typePtr == app->ProcBodyType) {
982 /* fall through: return tcl object. */
983 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000984
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000985 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200986#if TCL_UTF_MAX==3
987 return PyUnicode_FromKindAndData(
988 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
989 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000990#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200991 return PyUnicode_FromKindAndData(
992 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
993 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000994#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000995 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000996
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000997 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000998}
999
Benjamin Peterson5879d412009-03-30 14:51:56 +00001000#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001001/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001002TCL_DECLARE_MUTEX(call_mutex)
1003
1004typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001005 Tcl_Event ev; /* Must be first */
1006 TkappObject *self;
1007 PyObject *args;
1008 int flags;
1009 PyObject **res;
1010 PyObject **exc_type, **exc_value, **exc_tb;
1011 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001012} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001013#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001014
1015void
1016Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001017{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001018 int i;
1019 for (i = 0; i < objc; i++)
1020 Tcl_DecrRefCount(objv[i]);
1021 if (objv != objStore)
1022 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001023}
Guido van Rossum18468821994-06-20 07:49:28 +00001024
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001025/* Convert Python objects to Tcl objects. This must happen in the
1026 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001027
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001028static Tcl_Obj**
1029Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1030{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001031 Tcl_Obj **objv = objStore;
1032 int objc = 0, i;
1033 if (args == NULL)
1034 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001035
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001036 else if (!PyTuple_Check(args)) {
1037 objv[0] = AsObj(args);
1038 if (objv[0] == 0)
1039 goto finally;
1040 objc = 1;
1041 Tcl_IncrRefCount(objv[0]);
1042 }
1043 else {
1044 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001045
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001046 if (objc > ARGSZ) {
1047 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1048 if (objv == NULL) {
1049 PyErr_NoMemory();
1050 objc = 0;
1051 goto finally;
1052 }
1053 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001054
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 for (i = 0; i < objc; i++) {
1056 PyObject *v = PyTuple_GetItem(args, i);
1057 if (v == Py_None) {
1058 objc = i;
1059 break;
1060 }
1061 objv[i] = AsObj(v);
1062 if (!objv[i]) {
1063 /* Reset objc, so it attempts to clear
1064 objects only up to i. */
1065 objc = i;
1066 goto finally;
1067 }
1068 Tcl_IncrRefCount(objv[i]);
1069 }
1070 }
1071 *pobjc = objc;
1072 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001073finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001074 Tkapp_CallDeallocArgs(objv, objStore, objc);
1075 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001076}
Guido van Rossum212643f1998-04-29 16:22:14 +00001077
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001078/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001079
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001080static PyObject*
1081Tkapp_CallResult(TkappObject *self)
1082{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001083 PyObject *res = NULL;
1084 if(self->wantobjects) {
1085 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1086 /* Not sure whether the IncrRef is necessary, but something
1087 may overwrite the interpreter result while we are
1088 converting it. */
1089 Tcl_IncrRefCount(value);
1090 res = FromObj((PyObject*)self, value);
1091 Tcl_DecrRefCount(value);
1092 } else {
1093 const char *s = Tcl_GetStringResult(self->interp);
1094 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001095
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001096 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1097 }
1098 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001099}
Guido van Rossum632de272000-03-29 00:19:50 +00001100
Benjamin Peterson5879d412009-03-30 14:51:56 +00001101#ifdef WITH_THREAD
1102
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001103/* Tkapp_CallProc is the event procedure that is executed in the context of
1104 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1105 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001106
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001107static int
1108Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1109{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001110 Tcl_Obj *objStore[ARGSZ];
1111 Tcl_Obj **objv;
1112 int objc;
1113 int i;
1114 ENTER_PYTHON
1115 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1116 if (!objv) {
1117 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1118 *(e->res) = NULL;
1119 }
1120 LEAVE_PYTHON
1121 if (!objv)
1122 goto done;
1123 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1124 ENTER_PYTHON
1125 if (i == TCL_ERROR) {
1126 *(e->res) = NULL;
1127 *(e->exc_type) = NULL;
1128 *(e->exc_tb) = NULL;
1129 *(e->exc_value) = PyObject_CallFunction(
1130 Tkinter_TclError, "s",
1131 Tcl_GetStringResult(e->self->interp));
1132 }
1133 else {
1134 *(e->res) = Tkapp_CallResult(e->self);
1135 }
1136 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001137
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001138 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001139done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001140 /* Wake up calling thread. */
1141 Tcl_MutexLock(&call_mutex);
1142 Tcl_ConditionNotify(e->done);
1143 Tcl_MutexUnlock(&call_mutex);
1144 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001145}
1146
Benjamin Peterson5879d412009-03-30 14:51:56 +00001147#endif
1148
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001149/* This is the main entry point for calling a Tcl command.
1150 It supports three cases, with regard to threading:
1151 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1152 the context of the calling thread.
1153 2. Tcl is threaded, caller of the command is in the interpreter thread:
1154 Execute the command in the calling thread. Since the Tcl lock will
1155 not be used, we can merge that with case 1.
1156 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1157 the interpreter thread. Allocation of Tcl objects needs to occur in the
1158 interpreter thread, so we ship the PyObject* args to the target thread,
1159 and perform processing there. */
1160
1161static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001162Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001163{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001164 Tcl_Obj *objStore[ARGSZ];
1165 Tcl_Obj **objv = NULL;
1166 int objc, i;
1167 PyObject *res = NULL;
1168 TkappObject *self = (TkappObject*)selfptr;
1169 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001170
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001171 /* If args is a single tuple, replace with contents of tuple */
1172 if (1 == PyTuple_Size(args)){
1173 PyObject* item = PyTuple_GetItem(args, 0);
1174 if (PyTuple_Check(item))
1175 args = item;
1176 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001177#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001178 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1179 /* We cannot call the command directly. Instead, we must
1180 marshal the parameters to the interpreter thread. */
1181 Tkapp_CallEvent *ev;
1182 Tcl_Condition cond = NULL;
1183 PyObject *exc_type, *exc_value, *exc_tb;
1184 if (!WaitForMainloop(self))
1185 return NULL;
1186 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1187 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1188 ev->self = self;
1189 ev->args = args;
1190 ev->res = &res;
1191 ev->exc_type = &exc_type;
1192 ev->exc_value = &exc_value;
1193 ev->exc_tb = &exc_tb;
1194 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001195
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001196 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001198 if (res == NULL) {
1199 if (exc_type)
1200 PyErr_Restore(exc_type, exc_value, exc_tb);
1201 else
1202 PyErr_SetObject(Tkinter_TclError, exc_value);
1203 }
1204 Tcl_ConditionFinalize(&cond);
1205 }
1206 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001207#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001208 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001209
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001210 objv = Tkapp_CallArgs(args, objStore, &objc);
1211 if (!objv)
1212 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001213
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001214 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001215
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001216 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001217
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001218 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001219
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001220 if (i == TCL_ERROR)
1221 Tkinter_Error(selfptr);
1222 else
1223 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001224
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001225 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001226
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001227 Tkapp_CallDeallocArgs(objv, objStore, objc);
1228 }
1229 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001230}
1231
1232
1233static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001234Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001235{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001236 char *script;
1237 PyObject *res = NULL;
1238 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001239
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001240 if (!PyArg_ParseTuple(args, "s:eval", &script))
1241 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001242
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001243 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001244
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001245 ENTER_TCL
1246 err = Tcl_Eval(Tkapp_Interp(self), script);
1247 ENTER_OVERLAP
1248 if (err == TCL_ERROR)
1249 res = Tkinter_Error(self);
1250 else
1251 res = PyUnicode_FromString(Tkapp_Result(self));
1252 LEAVE_OVERLAP_TCL
1253 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001254}
1255
1256static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001257Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001258{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001259 char *fileName;
1260 PyObject *res = NULL;
1261 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001262
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001263 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1264 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001265
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001266 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001267
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001268 ENTER_TCL
1269 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1270 ENTER_OVERLAP
1271 if (err == TCL_ERROR)
1272 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001273
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001274 else
1275 res = PyUnicode_FromString(Tkapp_Result(self));
1276 LEAVE_OVERLAP_TCL
1277 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001278}
1279
1280static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001281Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001282{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001283 char *script;
1284 PyObject *res = NULL;
1285 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001287 if (!PyArg_ParseTuple(args, "s", &script))
1288 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001289
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001290 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001291
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001292 ENTER_TCL
1293 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1294 ENTER_OVERLAP
1295 if (err == TCL_ERROR)
1296 res = Tkinter_Error(self);
1297 else
1298 res = PyUnicode_FromString(Tkapp_Result(self));
1299 LEAVE_OVERLAP_TCL
1300 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001301}
1302
1303static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001304Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001305{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001306 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001307
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001308 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1309 return NULL;
1310 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001312 ENTER_TCL
1313 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1314 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001315
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001316 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001317}
1318
Barry Warsawfa701a81997-01-16 00:15:11 +00001319
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001320
Guido van Rossum18468821994-06-20 07:49:28 +00001321/** Tcl Variable **/
1322
Benjamin Peterson5879d412009-03-30 14:51:56 +00001323typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1324
1325#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001326TCL_DECLARE_MUTEX(var_mutex)
1327
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001328typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001329 Tcl_Event ev; /* must be first */
1330 PyObject *self;
1331 PyObject *args;
1332 int flags;
1333 EventFunc func;
1334 PyObject **res;
1335 PyObject **exc_type;
1336 PyObject **exc_val;
1337 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001338} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001339#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001340
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001341static int
1342varname_converter(PyObject *in, void *_out)
1343{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001344 char **out = (char**)_out;
1345 if (PyBytes_Check(in)) {
1346 *out = PyBytes_AsString(in);
1347 return 1;
1348 }
1349 if (PyUnicode_Check(in)) {
1350 *out = _PyUnicode_AsString(in);
1351 return 1;
1352 }
1353 if (PyTclObject_Check(in)) {
1354 *out = PyTclObject_TclString(in);
1355 return 1;
1356 }
1357 /* XXX: Should give diagnostics. */
1358 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001359}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001360
Benjamin Peterson5879d412009-03-30 14:51:56 +00001361#ifdef WITH_THREAD
1362
Martin v. Löwis59683e82008-06-13 07:50:45 +00001363static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001364var_perform(VarEvent *ev)
1365{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001366 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1367 if (!*(ev->res)) {
1368 PyObject *exc, *val, *tb;
1369 PyErr_Fetch(&exc, &val, &tb);
1370 PyErr_NormalizeException(&exc, &val, &tb);
1371 *(ev->exc_type) = exc;
1372 *(ev->exc_val) = val;
1373 Py_DECREF(tb);
1374 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001375
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001376}
1377
1378static int
1379var_proc(VarEvent* ev, int flags)
1380{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001381 ENTER_PYTHON
1382 var_perform(ev);
1383 Tcl_MutexLock(&var_mutex);
1384 Tcl_ConditionNotify(ev->cond);
1385 Tcl_MutexUnlock(&var_mutex);
1386 LEAVE_PYTHON
1387 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001388}
1389
Benjamin Peterson5879d412009-03-30 14:51:56 +00001390#endif
1391
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001392static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001393var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001394{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001395#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001396 TkappObject *self = (TkappObject*)selfptr;
1397 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1398 TkappObject *self = (TkappObject*)selfptr;
1399 VarEvent *ev;
1400 PyObject *res, *exc_type, *exc_val;
1401 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001403 /* The current thread is not the interpreter thread. Marshal
1404 the call to the interpreter thread, then wait for
1405 completion. */
1406 if (!WaitForMainloop(self))
1407 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001409 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001411 ev->self = selfptr;
1412 ev->args = args;
1413 ev->flags = flags;
1414 ev->func = func;
1415 ev->res = &res;
1416 ev->exc_type = &exc_type;
1417 ev->exc_val = &exc_val;
1418 ev->cond = &cond;
1419 ev->ev.proc = (Tcl_EventProc*)var_proc;
1420 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1421 Tcl_ConditionFinalize(&cond);
1422 if (!res) {
1423 PyErr_SetObject(exc_type, exc_val);
1424 Py_DECREF(exc_type);
1425 Py_DECREF(exc_val);
1426 return NULL;
1427 }
1428 return res;
1429 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001430#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001431 /* Tcl is not threaded, or this is the interpreter thread. */
1432 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001433}
1434
Guido van Rossum18468821994-06-20 07:49:28 +00001435static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001436SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001437{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001438 char *name1, *name2;
1439 PyObject *newValue;
1440 PyObject *res = NULL;
1441 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001443 if (PyArg_ParseTuple(args, "O&O:setvar",
1444 varname_converter, &name1, &newValue)) {
1445 /* XXX Acquire tcl lock??? */
1446 newval = AsObj(newValue);
1447 if (newval == NULL)
1448 return NULL;
1449 ENTER_TCL
1450 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1451 newval, flags);
1452 ENTER_OVERLAP
1453 if (!ok)
1454 Tkinter_Error(self);
1455 else {
1456 res = Py_None;
1457 Py_INCREF(res);
1458 }
1459 LEAVE_OVERLAP_TCL
1460 }
1461 else {
1462 PyErr_Clear();
1463 if (PyArg_ParseTuple(args, "ssO:setvar",
1464 &name1, &name2, &newValue)) {
1465 /* XXX must hold tcl lock already??? */
1466 newval = AsObj(newValue);
1467 ENTER_TCL
1468 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1469 ENTER_OVERLAP
1470 if (!ok)
1471 Tkinter_Error(self);
1472 else {
1473 res = Py_None;
1474 Py_INCREF(res);
1475 }
1476 LEAVE_OVERLAP_TCL
1477 }
1478 else {
1479 return NULL;
1480 }
1481 }
1482 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001483}
1484
1485static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001486Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001487{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001488 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001489}
1490
1491static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001492Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001493{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001494 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001495}
1496
Barry Warsawfa701a81997-01-16 00:15:11 +00001497
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001498
Guido van Rossum18468821994-06-20 07:49:28 +00001499static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001500GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001501{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001502 char *name1, *name2=NULL;
1503 PyObject *res = NULL;
1504 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001506 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1507 varname_converter, &name1, &name2))
1508 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510 ENTER_TCL
1511 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1512 ENTER_OVERLAP
1513 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001514 PyErr_SetString(Tkinter_TclError,
1515 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001516 } else {
1517 if (((TkappObject*)self)->wantobjects) {
1518 res = FromObj(self, tres);
1519 }
1520 else {
1521 res = PyUnicode_FromString(Tcl_GetString(tres));
1522 }
1523 }
1524 LEAVE_OVERLAP_TCL
1525 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001526}
1527
1528static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001529Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001530{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001531 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001532}
1533
1534static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001535Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001536{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001537 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001538}
1539
Barry Warsawfa701a81997-01-16 00:15:11 +00001540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541
Guido van Rossum18468821994-06-20 07:49:28 +00001542static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001543UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001544{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001545 char *name1, *name2=NULL;
1546 int code;
1547 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001548
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001549 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1550 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001551
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001552 ENTER_TCL
1553 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1554 ENTER_OVERLAP
1555 if (code == TCL_ERROR)
1556 res = Tkinter_Error(self);
1557 else {
1558 Py_INCREF(Py_None);
1559 res = Py_None;
1560 }
1561 LEAVE_OVERLAP_TCL
1562 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001563}
1564
1565static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001566Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001567{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001569}
1570
1571static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001572Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001573{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001574 return var_invoke(UnsetVar, self, args,
1575 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001576}
1577
Barry Warsawfa701a81997-01-16 00:15:11 +00001578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001579
Guido van Rossum18468821994-06-20 07:49:28 +00001580/** Tcl to Python **/
1581
1582static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001583Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001584{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001585 char *s;
1586 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001587
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001588 if (PyTuple_Size(args) == 1) {
1589 PyObject* o = PyTuple_GetItem(args, 0);
1590 if (PyLong_Check(o)) {
1591 Py_INCREF(o);
1592 return o;
1593 }
1594 }
1595 if (!PyArg_ParseTuple(args, "s:getint", &s))
1596 return NULL;
1597 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1598 return Tkinter_Error(self);
1599 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001600}
1601
1602static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001603Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001604{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001605 char *s;
1606 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001607
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001608 if (PyTuple_Size(args) == 1) {
1609 PyObject *o = PyTuple_GetItem(args, 0);
1610 if (PyFloat_Check(o)) {
1611 Py_INCREF(o);
1612 return o;
1613 }
1614 }
1615 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1616 return NULL;
1617 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1618 return Tkinter_Error(self);
1619 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001620}
1621
1622static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001623Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001624{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001625 char *s;
1626 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001628 if (PyTuple_Size(args) == 1) {
1629 PyObject *o = PyTuple_GetItem(args, 0);
1630 if (PyLong_Check(o)) {
1631 Py_INCREF(o);
1632 return o;
1633 }
1634 }
1635 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1636 return NULL;
1637 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1638 return Tkinter_Error(self);
1639 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001640}
1641
1642static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001643Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001644{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001645 char *s;
1646 PyObject *res = NULL;
1647 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001648
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001649 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1650 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001651
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001652 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001654 ENTER_TCL
1655 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1656 ENTER_OVERLAP
1657 if (retval == TCL_ERROR)
1658 res = Tkinter_Error(self);
1659 else
1660 res = Py_BuildValue("s", Tkapp_Result(self));
1661 LEAVE_OVERLAP_TCL
1662 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001663}
1664
1665static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001666Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001667{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001668 char *s;
1669 PyObject *res = NULL;
1670 int retval;
1671 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001673 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1674 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001676 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001677
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001678 ENTER_TCL
1679 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1680 ENTER_OVERLAP
1681 if (retval == TCL_ERROR)
1682 res = Tkinter_Error(self);
1683 else
1684 res = Py_BuildValue("l", v);
1685 LEAVE_OVERLAP_TCL
1686 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001687}
1688
1689static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001690Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001691{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001692 char *s;
1693 PyObject *res = NULL;
1694 double v;
1695 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001696
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001697 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1698 return NULL;
1699 CHECK_TCL_APPARTMENT;
1700 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1701 ENTER_TCL
1702 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1703 ENTER_OVERLAP
1704 PyFPE_END_PROTECT(retval)
1705 if (retval == TCL_ERROR)
1706 res = Tkinter_Error(self);
1707 else
1708 res = Py_BuildValue("d", v);
1709 LEAVE_OVERLAP_TCL
1710 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001711}
1712
1713static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001714Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001715{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001716 char *s;
1717 PyObject *res = NULL;
1718 int retval;
1719 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001720
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001721 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1722 return NULL;
1723 CHECK_TCL_APPARTMENT;
1724 ENTER_TCL
1725 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1726 ENTER_OVERLAP
1727 if (retval == TCL_ERROR)
1728 res = Tkinter_Error(self);
1729 else
1730 res = Py_BuildValue("i", v);
1731 LEAVE_OVERLAP_TCL
1732 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001733}
1734
Barry Warsawfa701a81997-01-16 00:15:11 +00001735
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001736
Guido van Rossum18468821994-06-20 07:49:28 +00001737static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001738Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001739{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001740 char *list;
1741 int argc;
1742 char **argv;
1743 PyObject *v;
1744 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001745
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001746 if (PyTuple_Size(args) == 1) {
1747 v = PyTuple_GetItem(args, 0);
1748 if (PyTuple_Check(v)) {
1749 Py_INCREF(v);
1750 return v;
1751 }
1752 }
1753 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1754 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001755
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001756 if (Tcl_SplitList(Tkapp_Interp(self), list,
1757 &argc, &argv) == TCL_ERROR) {
1758 PyMem_Free(list);
1759 return Tkinter_Error(self);
1760 }
Guido van Rossum18468821994-06-20 07:49:28 +00001761
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001762 if (!(v = PyTuple_New(argc)))
1763 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001764
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001765 for (i = 0; i < argc; i++) {
1766 PyObject *s = PyUnicode_FromString(argv[i]);
1767 if (!s || PyTuple_SetItem(v, i, s)) {
1768 Py_DECREF(v);
1769 v = NULL;
1770 goto finally;
1771 }
1772 }
Guido van Rossum18468821994-06-20 07:49:28 +00001773
Barry Warsawfa701a81997-01-16 00:15:11 +00001774 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 ckfree(FREECAST argv);
1776 PyMem_Free(list);
1777 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001778}
1779
1780static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001781Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001782{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001783 PyObject *v;
1784 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001786 if (PyTuple_Size(args) == 1) {
1787 PyObject* o = PyTuple_GetItem(args, 0);
1788 if (PyTuple_Check(o)) {
1789 o = SplitObj(o);
1790 return o;
1791 }
1792 }
1793 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1794 return NULL;
1795 v = Split(list);
1796 PyMem_Free(list);
1797 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001798}
1799
Barry Warsawfa701a81997-01-16 00:15:11 +00001800
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001801
Guido van Rossum18468821994-06-20 07:49:28 +00001802/** Tcl Command **/
1803
Guido van Rossum00d93061998-05-28 23:06:38 +00001804/* Client data struct */
1805typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001806 PyObject *self;
1807 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001808} PythonCmd_ClientData;
1809
1810static int
Fred Drake509d79a2000-07-08 04:04:38 +00001811PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001812{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001813 errorInCmd = 1;
1814 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1815 LEAVE_PYTHON
1816 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001817}
1818
Guido van Rossum18468821994-06-20 07:49:28 +00001819/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001820 * function or method.
1821 */
Guido van Rossum18468821994-06-20 07:49:28 +00001822static int
Fred Drake509d79a2000-07-08 04:04:38 +00001823PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001824{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001825 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001826 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001827 int i, rv;
1828 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001829
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001830 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001831
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001832 /* TBD: no error checking here since we know, via the
1833 * Tkapp_CreateCommand() that the client data is a two-tuple
1834 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001835 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001837 /* Create argument list (argv1, ..., argvN) */
1838 if (!(arg = PyTuple_New(argc - 1)))
1839 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001840
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001841 for (i = 0; i < (argc - 1); i++) {
1842 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04001843 if (!s) {
1844 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
1845 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
1846 !strcmp(argv[i + 1], "\xC0\x80")) {
1847 PyErr_Clear();
1848 /* Convert to "strict" utf-8 null */
1849 s = PyUnicode_FromString("\0");
1850 } else {
1851 Py_DECREF(arg);
1852 return PythonCmd_Error(interp);
1853 }
1854 }
1855 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001856 Py_DECREF(arg);
1857 return PythonCmd_Error(interp);
1858 }
1859 }
1860 res = PyEval_CallObject(func, arg);
1861 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001862
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001863 if (res == NULL)
1864 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001865
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001866 obj_res = AsObj(res);
1867 if (obj_res == NULL) {
1868 Py_DECREF(res);
1869 return PythonCmd_Error(interp);
1870 }
1871 else {
1872 Tcl_SetObjResult(interp, obj_res);
1873 rv = TCL_OK;
1874 }
Guido van Rossum2834b972000-10-06 16:58:26 +00001875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001876 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001877
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001878 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001879
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001880 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001881}
1882
1883static void
Fred Drake509d79a2000-07-08 04:04:38 +00001884PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001885{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001886 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00001887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001888 ENTER_PYTHON
1889 Py_XDECREF(data->self);
1890 Py_XDECREF(data->func);
1891 PyMem_DEL(data);
1892 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001893}
1894
Barry Warsawfa701a81997-01-16 00:15:11 +00001895
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001896
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001897
Benjamin Peterson5879d412009-03-30 14:51:56 +00001898#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001899TCL_DECLARE_MUTEX(command_mutex)
1900
1901typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001902 Tcl_Event ev;
1903 Tcl_Interp* interp;
1904 char *name;
1905 int create;
1906 int *status;
1907 ClientData *data;
1908 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001909} CommandEvent;
1910
1911static int
1912Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001913{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001914 if (ev->create)
1915 *ev->status = Tcl_CreateCommand(
1916 ev->interp, ev->name, PythonCmd,
1917 ev->data, PythonCmdDelete) == NULL;
1918 else
1919 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1920 Tcl_MutexLock(&command_mutex);
1921 Tcl_ConditionNotify(ev->done);
1922 Tcl_MutexUnlock(&command_mutex);
1923 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001924}
Benjamin Peterson5879d412009-03-30 14:51:56 +00001925#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001926
1927static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001928Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001929{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001930 TkappObject *self = (TkappObject*)selfptr;
1931 PythonCmd_ClientData *data;
1932 char *cmdName;
1933 PyObject *func;
1934 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001935
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001936 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
1937 return NULL;
1938 if (!PyCallable_Check(func)) {
1939 PyErr_SetString(PyExc_TypeError, "command not callable");
1940 return NULL;
1941 }
Guido van Rossum18468821994-06-20 07:49:28 +00001942
Martin v. Löwisa9656492003-03-30 08:44:58 +00001943#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001944 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
1945 !WaitForMainloop(self))
1946 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001947#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001948
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001949 data = PyMem_NEW(PythonCmd_ClientData, 1);
1950 if (!data)
1951 return PyErr_NoMemory();
1952 Py_INCREF(self);
1953 Py_INCREF(func);
1954 data->self = selfptr;
1955 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001956#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001957 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1958 Tcl_Condition cond = NULL;
1959 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
1960 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
1961 ev->interp = self->interp;
1962 ev->create = 1;
1963 ev->name = cmdName;
1964 ev->data = (ClientData)data;
1965 ev->status = &err;
1966 ev->done = &cond;
1967 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
1968 Tcl_ConditionFinalize(&cond);
1969 }
1970 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00001971#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001972 {
1973 ENTER_TCL
1974 err = Tcl_CreateCommand(
1975 Tkapp_Interp(self), cmdName, PythonCmd,
1976 (ClientData)data, PythonCmdDelete) == NULL;
1977 LEAVE_TCL
1978 }
1979 if (err) {
1980 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
1981 PyMem_DEL(data);
1982 return NULL;
1983 }
Guido van Rossum18468821994-06-20 07:49:28 +00001984
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001985 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001986}
1987
Barry Warsawfa701a81997-01-16 00:15:11 +00001988
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001989
Guido van Rossum18468821994-06-20 07:49:28 +00001990static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001991Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001992{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001993 TkappObject *self = (TkappObject*)selfptr;
1994 char *cmdName;
1995 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001996
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001997 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
1998 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001999
2000#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002001 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2002 Tcl_Condition cond = NULL;
2003 CommandEvent *ev;
2004 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2005 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2006 ev->interp = self->interp;
2007 ev->create = 0;
2008 ev->name = cmdName;
2009 ev->status = &err;
2010 ev->done = &cond;
2011 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2012 &command_mutex);
2013 Tcl_ConditionFinalize(&cond);
2014 }
2015 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002016#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002017 {
2018 ENTER_TCL
2019 err = Tcl_DeleteCommand(self->interp, cmdName);
2020 LEAVE_TCL
2021 }
2022 if (err == -1) {
2023 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2024 return NULL;
2025 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002026 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002027}
2028
Barry Warsawfa701a81997-01-16 00:15:11 +00002029
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002030
Guido van Rossum00d93061998-05-28 23:06:38 +00002031#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002032/** File Handler **/
2033
Guido van Rossum00d93061998-05-28 23:06:38 +00002034typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002035 PyObject *func;
2036 PyObject *file;
2037 int id;
2038 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002039} FileHandler_ClientData;
2040
2041static FileHandler_ClientData *HeadFHCD;
2042
2043static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002044NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002045{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002046 FileHandler_ClientData *p;
2047 p = PyMem_NEW(FileHandler_ClientData, 1);
2048 if (p != NULL) {
2049 Py_XINCREF(func);
2050 Py_XINCREF(file);
2051 p->func = func;
2052 p->file = file;
2053 p->id = id;
2054 p->next = HeadFHCD;
2055 HeadFHCD = p;
2056 }
2057 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002058}
2059
2060static void
Fred Drake509d79a2000-07-08 04:04:38 +00002061DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002062{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002065 pp = &HeadFHCD;
2066 while ((p = *pp) != NULL) {
2067 if (p->id == id) {
2068 *pp = p->next;
2069 Py_XDECREF(p->func);
2070 Py_XDECREF(p->file);
2071 PyMem_DEL(p);
2072 }
2073 else
2074 pp = &p->next;
2075 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002076}
2077
Guido van Rossuma597dde1995-01-10 20:56:29 +00002078static void
Fred Drake509d79a2000-07-08 04:04:38 +00002079FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002080{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002081 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2082 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002083
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002084 ENTER_PYTHON
2085 func = data->func;
2086 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002088 arg = Py_BuildValue("(Oi)", file, (long) mask);
2089 res = PyEval_CallObject(func, arg);
2090 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002091
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002092 if (res == NULL) {
2093 errorInCmd = 1;
2094 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2095 }
2096 Py_XDECREF(res);
2097 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002098}
2099
Guido van Rossum18468821994-06-20 07:49:28 +00002100static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002101Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2102 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002103{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002104 FileHandler_ClientData *data;
2105 PyObject *file, *func;
2106 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002107
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002108 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2109 &file, &mask, &func))
2110 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002112 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002113
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002114 tfile = PyObject_AsFileDescriptor(file);
2115 if (tfile < 0)
2116 return NULL;
2117 if (!PyCallable_Check(func)) {
2118 PyErr_SetString(PyExc_TypeError, "bad argument list");
2119 return NULL;
2120 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002121
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002122 data = NewFHCD(func, file, tfile);
2123 if (data == NULL)
2124 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002125
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002126 /* Ought to check for null Tcl_File object... */
2127 ENTER_TCL
2128 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2129 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002130 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002131}
2132
2133static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002134Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002135{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002136 PyObject *file;
2137 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002138
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002139 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2140 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002141
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002143
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002144 tfile = PyObject_AsFileDescriptor(file);
2145 if (tfile < 0)
2146 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002147
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002148 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002149
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002150 /* Ought to check for null Tcl_File object... */
2151 ENTER_TCL
2152 Tcl_DeleteFileHandler(tfile);
2153 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002154 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002155}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002156#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002157
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002158
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002159/**** Tktt Object (timer token) ****/
2160
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002161static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002162
Guido van Rossum00d93061998-05-28 23:06:38 +00002163typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002164 PyObject_HEAD
2165 Tcl_TimerToken token;
2166 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002167} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002168
2169static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002170Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002171{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002172 TkttObject *v = (TkttObject *)self;
2173 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002174
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002175 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2176 return NULL;
2177 if (v->token != NULL) {
2178 Tcl_DeleteTimerHandler(v->token);
2179 v->token = NULL;
2180 }
2181 if (func != NULL) {
2182 v->func = NULL;
2183 Py_DECREF(func);
2184 Py_DECREF(v); /* See Tktt_New() */
2185 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002186 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002187}
2188
2189static PyMethodDef Tktt_methods[] =
2190{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002191 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2192 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002193};
2194
2195static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002196Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002197{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002198 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002199
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002200 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002201 if (v == NULL)
2202 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002203 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002204
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002205 Py_INCREF(func);
2206 v->token = NULL;
2207 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002208
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002209 /* Extra reference, deleted when called or when handler is deleted */
2210 Py_INCREF(v);
2211 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002212}
2213
2214static void
Fred Drake509d79a2000-07-08 04:04:38 +00002215Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002216{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002217 TkttObject *v = (TkttObject *)self;
2218 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002219 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002220
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002221 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002222
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002223 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002224 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002225}
2226
Guido van Rossum597ac201998-05-12 14:36:19 +00002227static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002228Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002229{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002230 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002231 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2232 v,
2233 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002234}
2235
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002236static PyType_Slot Tktt_Type_slots[] = {
2237 {Py_tp_dealloc, Tktt_Dealloc},
2238 {Py_tp_repr, Tktt_Repr},
2239 {Py_tp_methods, Tktt_methods},
2240 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002241};
2242
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002243static PyType_Spec Tktt_Type_spec = {
2244 "tktimertoken",
2245 sizeof(TkttObject),
2246 0,
2247 Py_TPFLAGS_DEFAULT,
2248 Tktt_Type_slots,
2249};
Barry Warsawfa701a81997-01-16 00:15:11 +00002250
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002251
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002252/** Timer Handler **/
2253
2254static void
Fred Drake509d79a2000-07-08 04:04:38 +00002255TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002256{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002257 TkttObject *v = (TkttObject *)clientData;
2258 PyObject *func = v->func;
2259 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002261 if (func == NULL)
2262 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002263
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002264 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002265
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002266 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002267
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002268 res = PyEval_CallObject(func, NULL);
2269 Py_DECREF(func);
2270 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002271
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002272 if (res == NULL) {
2273 errorInCmd = 1;
2274 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2275 }
2276 else
2277 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002278
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002279 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002280}
2281
2282static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002283Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002284{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002285 int milliseconds;
2286 PyObject *func;
2287 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002288
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002289 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2290 &milliseconds, &func))
2291 return NULL;
2292 if (!PyCallable_Check(func)) {
2293 PyErr_SetString(PyExc_TypeError, "bad argument list");
2294 return NULL;
2295 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002297 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299 v = Tktt_New(func);
2300 if (v) {
2301 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2302 (ClientData)v);
2303 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002304
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002305 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002306}
2307
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002308
Guido van Rossum18468821994-06-20 07:49:28 +00002309/** Event Loop **/
2310
Guido van Rossum18468821994-06-20 07:49:28 +00002311static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002312Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002313{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002314 int threshold = 0;
2315 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002316#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002317 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002318#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002319
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002320 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2321 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002322
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002323 CHECK_TCL_APPARTMENT;
2324 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002326 quitMainLoop = 0;
2327 while (Tk_GetNumMainWindows() > threshold &&
2328 !quitMainLoop &&
2329 !errorInCmd)
2330 {
2331 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002332
2333#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002334 if (self->threaded) {
2335 /* Allow other Python threads to run. */
2336 ENTER_TCL
2337 result = Tcl_DoOneEvent(0);
2338 LEAVE_TCL
2339 }
2340 else {
2341 Py_BEGIN_ALLOW_THREADS
2342 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2343 tcl_tstate = tstate;
2344 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2345 tcl_tstate = NULL;
2346 if(tcl_lock)PyThread_release_lock(tcl_lock);
2347 if (result == 0)
2348 Sleep(Tkinter_busywaitinterval);
2349 Py_END_ALLOW_THREADS
2350 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002351#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002352 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002353#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002354
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002355 if (PyErr_CheckSignals() != 0) {
2356 self->dispatching = 0;
2357 return NULL;
2358 }
2359 if (result < 0)
2360 break;
2361 }
2362 self->dispatching = 0;
2363 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002364
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002365 if (errorInCmd) {
2366 errorInCmd = 0;
2367 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2368 excInCmd = valInCmd = trbInCmd = NULL;
2369 return NULL;
2370 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002371 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002372}
2373
2374static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002375Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002376{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002377 int flags = 0;
2378 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002380 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2381 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002382
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002383 ENTER_TCL
2384 rv = Tcl_DoOneEvent(flags);
2385 LEAVE_TCL
2386 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002387}
2388
2389static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002390Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002391{
2392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002393 if (!PyArg_ParseTuple(args, ":quit"))
2394 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002395
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002396 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002397 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002398}
2399
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002400static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002401Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002402{
2403
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002404 if (!PyArg_ParseTuple(args, ":interpaddr"))
2405 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 return PyLong_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002408}
2409
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002410static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002411Tkapp_TkInit(PyObject *self, PyObject *args)
2412{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002413 Tcl_Interp *interp = Tkapp_Interp(self);
2414 const char * _tk_exists = NULL;
2415 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002416
Guilherme Polob681df42009-02-09 22:33:59 +00002417#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002418 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2419 * first call failed.
2420 * To avoid the deadlock, we just refuse the second call through
2421 * a static variable.
2422 */
2423 if (tk_load_failed) {
2424 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2425 return NULL;
2426 }
Guilherme Polob681df42009-02-09 22:33:59 +00002427#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002429 /* We want to guard against calling Tk_Init() multiple times */
2430 CHECK_TCL_APPARTMENT;
2431 ENTER_TCL
2432 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2433 ENTER_OVERLAP
2434 if (err == TCL_ERROR) {
2435 /* This sets an exception, but we cannot return right
2436 away because we need to exit the overlap first. */
2437 Tkinter_Error(self);
2438 } else {
2439 _tk_exists = Tkapp_Result(self);
2440 }
2441 LEAVE_OVERLAP_TCL
2442 if (err == TCL_ERROR) {
2443 return NULL;
2444 }
2445 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2446 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002447 PyErr_SetString(Tkinter_TclError,
2448 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002449#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002450 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002451#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002452 return NULL;
2453 }
2454 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002455 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002456}
Barry Warsawfa701a81997-01-16 00:15:11 +00002457
Martin v. Löwisffad6332002-11-26 09:28:05 +00002458static PyObject *
2459Tkapp_WantObjects(PyObject *self, PyObject *args)
2460{
2461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002462 int wantobjects = -1;
2463 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2464 return NULL;
2465 if (wantobjects == -1)
2466 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2467 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002468
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002469 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002470}
2471
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002472static PyObject *
2473Tkapp_WillDispatch(PyObject *self, PyObject *args)
2474{
2475
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002476 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002477
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002478 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002479}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002480
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002481
Guido van Rossum18468821994-06-20 07:49:28 +00002482/**** Tkapp Method List ****/
2483
2484static PyMethodDef Tkapp_methods[] =
2485{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002486 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2487 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2488 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002489 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002490 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2491 {"record", Tkapp_Record, METH_VARARGS},
2492 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2493 {"setvar", Tkapp_SetVar, METH_VARARGS},
2494 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2495 {"getvar", Tkapp_GetVar, METH_VARARGS},
2496 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2497 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2498 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2499 {"getint", Tkapp_GetInt, METH_VARARGS},
2500 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2501 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2502 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2503 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2504 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2505 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2506 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2507 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2509 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002510#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002511 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2512 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002513#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002514 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2515 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2516 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2517 {"quit", Tkapp_Quit, METH_VARARGS},
2518 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2519 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2520 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002521};
2522
Barry Warsawfa701a81997-01-16 00:15:11 +00002523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002524
Guido van Rossum18468821994-06-20 07:49:28 +00002525/**** Tkapp Type Methods ****/
2526
2527static void
Fred Drake509d79a2000-07-08 04:04:38 +00002528Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002529{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002530 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002531 /*CHECK_TCL_APPARTMENT;*/
2532 ENTER_TCL
2533 Tcl_DeleteInterp(Tkapp_Interp(self));
2534 LEAVE_TCL
2535 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002536 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002537 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002538}
2539
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002540static PyType_Slot Tkapp_Type_slots[] = {
2541 {Py_tp_dealloc, Tkapp_Dealloc},
2542 {Py_tp_methods, Tkapp_methods},
2543 {0, 0}
2544};
2545
2546
2547static PyType_Spec Tkapp_Type_spec = {
2548 "tkapp",
2549 sizeof(TkappObject),
2550 0,
2551 Py_TPFLAGS_DEFAULT,
2552 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002553};
2554
Barry Warsawfa701a81997-01-16 00:15:11 +00002555
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002556
Guido van Rossum18468821994-06-20 07:49:28 +00002557/**** Tkinter Module ****/
2558
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002559typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560 PyObject* tuple;
2561 int size; /* current size */
2562 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002563} FlattenContext;
2564
2565static int
2566_bump(FlattenContext* context, int size)
2567{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002568 /* expand tuple to hold (at least) size new items.
2569 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002571 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002573 if (maxsize < context->size + size)
2574 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002576 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002578 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002579}
2580
2581static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002582_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002583{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002584 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002585
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002586 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002587
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002588 if (depth > 1000) {
2589 PyErr_SetString(PyExc_ValueError,
2590 "nesting too deep in _flatten");
2591 return 0;
2592 } else if (PyList_Check(item)) {
2593 size = PyList_GET_SIZE(item);
2594 /* preallocate (assume no nesting) */
2595 if (context->size + size > context->maxsize &&
2596 !_bump(context, size))
2597 return 0;
2598 /* copy items to output tuple */
2599 for (i = 0; i < size; i++) {
2600 PyObject *o = PyList_GET_ITEM(item, i);
2601 if (PyList_Check(o) || PyTuple_Check(o)) {
2602 if (!_flatten1(context, o, depth + 1))
2603 return 0;
2604 } else if (o != Py_None) {
2605 if (context->size + 1 > context->maxsize &&
2606 !_bump(context, 1))
2607 return 0;
2608 Py_INCREF(o);
2609 PyTuple_SET_ITEM(context->tuple,
2610 context->size++, o);
2611 }
2612 }
2613 } else if (PyTuple_Check(item)) {
2614 /* same, for tuples */
2615 size = PyTuple_GET_SIZE(item);
2616 if (context->size + size > context->maxsize &&
2617 !_bump(context, size))
2618 return 0;
2619 for (i = 0; i < size; i++) {
2620 PyObject *o = PyTuple_GET_ITEM(item, i);
2621 if (PyList_Check(o) || PyTuple_Check(o)) {
2622 if (!_flatten1(context, o, depth + 1))
2623 return 0;
2624 } else if (o != Py_None) {
2625 if (context->size + 1 > context->maxsize &&
2626 !_bump(context, 1))
2627 return 0;
2628 Py_INCREF(o);
2629 PyTuple_SET_ITEM(context->tuple,
2630 context->size++, o);
2631 }
2632 }
2633 } else {
2634 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2635 return 0;
2636 }
2637 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002638}
2639
2640static PyObject *
2641Tkinter_Flatten(PyObject* self, PyObject* args)
2642{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002643 FlattenContext context;
2644 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002645
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002646 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2647 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002648
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002649 context.maxsize = PySequence_Size(item);
2650 if (context.maxsize < 0)
2651 return NULL;
2652 if (context.maxsize == 0)
2653 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002654
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002655 context.tuple = PyTuple_New(context.maxsize);
2656 if (!context.tuple)
2657 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002659 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002661 if (!_flatten1(&context, item,0))
2662 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002664 if (_PyTuple_Resize(&context.tuple, context.size))
2665 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002667 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002668}
2669
Guido van Rossum18468821994-06-20 07:49:28 +00002670static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002671Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002672{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002673 char *screenName = NULL;
2674 char *baseName = NULL; /* XXX this is not used anymore;
2675 try getting rid of it. */
2676 char *className = NULL;
2677 int interactive = 0;
2678 int wantobjects = 0;
2679 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2680 int sync = 0; /* pass -sync to wish */
2681 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002682
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002683 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002684
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002685 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2686 &screenName, &baseName, &className,
2687 &interactive, &wantobjects, &wantTk,
2688 &sync, &use))
2689 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002690
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002691 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002692 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002693 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002694}
2695
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002696static PyObject *
2697Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2698{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002699 int new_val;
2700 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2701 return NULL;
2702 if (new_val < 0) {
2703 PyErr_SetString(PyExc_ValueError,
2704 "busywaitinterval must be >= 0");
2705 return NULL;
2706 }
2707 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002708 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002709}
2710
2711static char setbusywaitinterval_doc[] =
2712"setbusywaitinterval(n) -> None\n\
2713\n\
2714Set the busy-wait interval in milliseconds between successive\n\
2715calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2716It should be set to a divisor of the maximum time between\n\
2717frames in an animation.";
2718
2719static PyObject *
2720Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2721{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002722 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002723}
2724
2725static char getbusywaitinterval_doc[] =
2726"getbusywaitinterval() -> int\n\
2727\n\
2728Return the current busy-wait interval between successive\n\
2729calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2730
Guido van Rossum18468821994-06-20 07:49:28 +00002731static PyMethodDef moduleMethods[] =
2732{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002733 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2734 {"create", Tkinter_Create, METH_VARARGS},
2735 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2736 setbusywaitinterval_doc},
2737 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2738 METH_NOARGS, getbusywaitinterval_doc},
2739 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002740};
2741
Guido van Rossum7bf15641998-05-22 18:28:17 +00002742#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002743
2744static int stdin_ready = 0;
2745
Guido van Rossumad4db171998-06-13 13:56:28 +00002746#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002747static void
Fred Drake509d79a2000-07-08 04:04:38 +00002748MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002749{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002750 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002751}
Guido van Rossumad4db171998-06-13 13:56:28 +00002752#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002753
Martin v. Löwisa9656492003-03-30 08:44:58 +00002754#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002755static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002756#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002757
Guido van Rossum18468821994-06-20 07:49:28 +00002758static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002759EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002760{
Guido van Rossumad4db171998-06-13 13:56:28 +00002761#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002762 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002763#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002764#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002765 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002766#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002767 stdin_ready = 0;
2768 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002769#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002770 tfile = fileno(stdin);
2771 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002772#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002773 while (!errorInCmd && !stdin_ready) {
2774 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002775#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002776 if (_kbhit()) {
2777 stdin_ready = 1;
2778 break;
2779 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002780#endif
2781#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002782 Py_BEGIN_ALLOW_THREADS
2783 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2784 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002786 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002787
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002788 tcl_tstate = NULL;
2789 if(tcl_lock)PyThread_release_lock(tcl_lock);
2790 if (result == 0)
2791 Sleep(Tkinter_busywaitinterval);
2792 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002793#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002795#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002796
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002797 if (result < 0)
2798 break;
2799 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002800#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002801 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002802#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002803 if (errorInCmd) {
2804 errorInCmd = 0;
2805 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2806 excInCmd = valInCmd = trbInCmd = NULL;
2807 PyErr_Print();
2808 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002809#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002810 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002811#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002812 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002813}
Guido van Rossum18468821994-06-20 07:49:28 +00002814
Guido van Rossum00d93061998-05-28 23:06:38 +00002815#endif
2816
Guido van Rossum7bf15641998-05-22 18:28:17 +00002817static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002818EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002819{
Guido van Rossum00d93061998-05-28 23:06:38 +00002820#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002821 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002822#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002823 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002824#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002825 PyOS_InputHook = EventHook;
2826 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002827#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002828}
2829
2830static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002831DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002832{
Guido van Rossum00d93061998-05-28 23:06:38 +00002833#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002834 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2835 PyOS_InputHook = NULL;
2836 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002837#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002838}
2839
Barry Warsawfa701a81997-01-16 00:15:11 +00002840
Martin v. Löwis1a214512008-06-11 05:26:20 +00002841static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002842 PyModuleDef_HEAD_INIT,
2843 "_tkinter",
2844 NULL,
2845 -1,
2846 moduleMethods,
2847 NULL,
2848 NULL,
2849 NULL,
2850 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002851};
2852
Mark Hammond62b1ab12002-07-23 06:31:15 +00002853PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002854PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002855{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002856 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00002857
Guido van Rossum00d93061998-05-28 23:06:38 +00002858#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002859 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002860 if (tcl_lock == NULL)
2861 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002862#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002863
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002864 m = PyModule_Create(&_tkintermodule);
2865 if (m == NULL)
2866 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002867
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002868 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
2869 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02002870 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002871 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02002872 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002873 Py_INCREF(o);
2874 if (PyModule_AddObject(m, "TclError", o)) {
2875 Py_DECREF(o);
2876 Py_DECREF(m);
2877 return NULL;
2878 }
2879 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002880
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002881 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
2882 Py_DECREF(m);
2883 return NULL;
2884 }
2885 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
2886 Py_DECREF(m);
2887 return NULL;
2888 }
2889 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
2890 Py_DECREF(m);
2891 return NULL;
2892 }
2893 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
2894 Py_DECREF(m);
2895 return NULL;
2896 }
2897 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
2898 Py_DECREF(m);
2899 return NULL;
2900 }
2901 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
2902 Py_DECREF(m);
2903 return NULL;
2904 }
2905 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
2906 Py_DECREF(m);
2907 return NULL;
2908 }
2909 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
2910 Py_DECREF(m);
2911 return NULL;
2912 }
2913 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
2914 Py_DECREF(m);
2915 return NULL;
2916 }
2917 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
2918 Py_DECREF(m);
2919 return NULL;
2920 }
2921 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
2922 Py_DECREF(m);
2923 return NULL;
2924 }
2925
2926 o = PyType_FromSpec(&Tkapp_Type_spec);
2927 if (o == NULL) {
2928 Py_DECREF(m);
2929 return NULL;
2930 }
2931 if (PyModule_AddObject(m, "TkappType", o)) {
2932 Py_DECREF(o);
2933 Py_DECREF(m);
2934 return NULL;
2935 }
2936 Tkapp_Type = o;
2937
2938 o = PyType_FromSpec(&Tktt_Type_spec);
2939 if (o == NULL) {
2940 Py_DECREF(m);
2941 return NULL;
2942 }
2943 if (PyModule_AddObject(m, "TkttType", o)) {
2944 Py_DECREF(o);
2945 Py_DECREF(m);
2946 return NULL;
2947 }
2948 Tktt_Type = o;
2949
2950 o = PyType_FromSpec(&PyTclObject_Type_spec);
2951 if (o == NULL) {
2952 Py_DECREF(m);
2953 return NULL;
2954 }
2955 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
2956 Py_DECREF(o);
2957 Py_DECREF(m);
2958 return NULL;
2959 }
2960 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00002961
2962#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002963 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2964 * start waking up. Note that Tcl_FindExecutable will do this, this
2965 * code must be above it! The original warning from
2966 * tkMacOSXAppInit.c is copied below.
2967 *
2968 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2969 * Tcl interpreter for now. It probably should work to do this
2970 * in the other order, but for now it doesn't seem to.
2971 *
2972 */
2973 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00002974#endif
2975
2976
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002977 /* This helps the dynamic loader; in Unicode aware Tcl versions
2978 it also helps Tcl find its encodings. */
2979 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
2980 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00002981 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002982 if (cexe)
2983 Tcl_FindExecutable(PyBytes_AsString(cexe));
2984 Py_XDECREF(cexe);
2985 Py_DECREF(uexe);
2986 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00002987
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002988 if (PyErr_Occurred()) {
2989 Py_DECREF(m);
2990 return NULL;
2991 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002992
Guido van Rossum43ff8681998-07-14 18:02:13 +00002993#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002994 /* This was not a good idea; through <Destroy> bindings,
2995 Tcl_Finalize() may invoke Python code but at that point the
2996 interpreter and thread state have already been destroyed! */
2997 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002998#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002999 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003000}