blob: 26f10fd397779cf3f9cfba2378fb0aa15a450539 [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;
Barry Warsawfa701a81997-01-16 00:15:11 +0000519
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000520 v->interp = Tcl_CreateInterp();
521 v->wantobjects = wantobjects;
522 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
523 TCL_GLOBAL_ONLY) != NULL;
524 v->thread_id = Tcl_GetCurrentThread();
525 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000526
527#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000528 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300529 PyErr_SetString(PyExc_RuntimeError,
530 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000531 Py_DECREF(v);
532 return 0;
533 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000534#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000535#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000536 if (v->threaded && tcl_lock) {
537 /* If Tcl is threaded, we don't need the lock. */
538 PyThread_free_lock(tcl_lock);
539 tcl_lock = NULL;
540 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000541#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000542
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000543 v->BooleanType = Tcl_GetObjType("boolean");
544 v->ByteArrayType = Tcl_GetObjType("bytearray");
545 v->DoubleType = Tcl_GetObjType("double");
546 v->IntType = Tcl_GetObjType("int");
547 v->ListType = Tcl_GetObjType("list");
548 v->ProcBodyType = Tcl_GetObjType("procbody");
549 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551 /* Delete the 'exit' command, which can screw things up */
552 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000553
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554 if (screenName != NULL)
555 Tcl_SetVar2(v->interp, "env", "DISPLAY",
556 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000557
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000558 if (interactive)
559 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
560 else
561 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000562
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000563 /* This is used to get the application class for Tk 4.1 and up */
564 argv0 = (char*)ckalloc(strlen(className) + 1);
565 if (!argv0) {
566 PyErr_NoMemory();
567 Py_DECREF(v);
568 return NULL;
569 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200572 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
573 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000574 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
575 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000576
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000577 if (! wantTk) {
578 Tcl_SetVar(v->interp,
579 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
580 }
Guilherme Polob681df42009-02-09 22:33:59 +0000581#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000582 else if (tk_load_failed) {
583 Tcl_SetVar(v->interp,
584 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
585 }
Guilherme Polob681df42009-02-09 22:33:59 +0000586#endif
David Aschere2b4b322004-02-18 05:59:53 +0000587
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000588 /* some initial arguments need to be in argv */
589 if (sync || use) {
590 char *args;
591 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 if (sync)
594 len += sizeof "-sync";
595 if (use)
596 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 args = (char*)ckalloc(len);
599 if (!args) {
600 PyErr_NoMemory();
601 Py_DECREF(v);
602 return NULL;
603 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000605 args[0] = '\0';
606 if (sync)
607 strcat(args, "-sync");
608 if (use) {
609 if (sync)
610 strcat(args, " ");
611 strcat(args, "-use ");
612 strcat(args, use);
613 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000614
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000615 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
616 ckfree(args);
617 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000619 if (Tcl_AppInit(v->interp) != TCL_OK) {
620 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000621#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000622 if (wantTk) {
623 const char *_tkinter_tk_failed;
624 _tkinter_tk_failed = Tcl_GetVar(v->interp,
625 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000626
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000627 if ( _tkinter_tk_failed != NULL &&
628 strcmp(_tkinter_tk_failed, "1") == 0) {
629 tk_load_failed = 1;
630 }
631 }
Guilherme Polob681df42009-02-09 22:33:59 +0000632#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 Py_DECREF((PyObject *)v);
634 return (TkappObject *)result;
635 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000638
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000640}
641
Barry Warsawfa701a81997-01-16 00:15:11 +0000642
Benjamin Peterson5879d412009-03-30 14:51:56 +0000643#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000644static void
645Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000646 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000647{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648 Py_BEGIN_ALLOW_THREADS;
649 Tcl_MutexLock(mutex);
650 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
651 Tcl_ThreadAlert(self->thread_id);
652 Tcl_ConditionWait(cond, mutex, NULL);
653 Tcl_MutexUnlock(mutex);
654 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000655}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000656#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658
Guido van Rossum18468821994-06-20 07:49:28 +0000659/** Tcl Eval **/
660
Martin v. Löwisffad6332002-11-26 09:28:05 +0000661typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 PyObject_HEAD
663 Tcl_Obj *value;
664 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000665} PyTclObject;
666
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300667static PyObject *PyTclObject_Type;
668#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000669
670static PyObject *
671newPyTclObject(Tcl_Obj *arg)
672{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000673 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300674 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000675 if (self == NULL)
676 return NULL;
677 Tcl_IncrRefCount(arg);
678 self->value = arg;
679 self->string = NULL;
680 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000681}
682
683static void
684PyTclObject_dealloc(PyTclObject *self)
685{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000686 Tcl_DecrRefCount(self->value);
687 Py_XDECREF(self->string);
688 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000689}
690
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000691static char*
692PyTclObject_TclString(PyObject *self)
693{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000695}
696
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000697/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000698PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000699"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000700
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000701static PyObject *
702PyTclObject_string(PyTclObject *self, void *ignored)
703{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000704 char *s;
705 int len;
706 if (!self->string) {
707 s = Tcl_GetStringFromObj(self->value, &len);
708 self->string = PyUnicode_FromStringAndSize(s, len);
709 if (!self->string)
710 return NULL;
711 }
712 Py_INCREF(self->string);
713 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000714}
715
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000716static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000717PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000718{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000719 char *s;
720 int len;
721 if (self->string && PyUnicode_Check(self->string)) {
722 Py_INCREF(self->string);
723 return self->string;
724 }
725 /* XXX Could chache result if it is non-ASCII. */
726 s = Tcl_GetStringFromObj(self->value, &len);
727 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000728}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000729
Martin v. Löwisffad6332002-11-26 09:28:05 +0000730static PyObject *
731PyTclObject_repr(PyTclObject *self)
732{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000733 return PyUnicode_FromFormat("<%s object at %p>",
734 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000735}
736
Mark Dickinson211c6252009-02-01 10:28:51 +0000737#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
738
739static PyObject *
740PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000741{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 int result;
743 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000744
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000745 /* neither argument should be NULL, unless something's gone wrong */
746 if (self == NULL || other == NULL) {
747 PyErr_BadInternalCall();
748 return NULL;
749 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000750
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000751 /* both arguments should be instances of PyTclObject */
752 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
753 v = Py_NotImplemented;
754 goto finished;
755 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000756
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000757 if (self == other)
758 /* fast path when self and other are identical */
759 result = 0;
760 else
761 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
762 Tcl_GetString(((PyTclObject *)other)->value));
763 /* Convert return value to a Boolean */
764 switch (op) {
765 case Py_EQ:
766 v = TEST_COND(result == 0);
767 break;
768 case Py_NE:
769 v = TEST_COND(result != 0);
770 break;
771 case Py_LE:
772 v = TEST_COND(result <= 0);
773 break;
774 case Py_GE:
775 v = TEST_COND(result >= 0);
776 break;
777 case Py_LT:
778 v = TEST_COND(result < 0);
779 break;
780 case Py_GT:
781 v = TEST_COND(result > 0);
782 break;
783 default:
784 PyErr_BadArgument();
785 return NULL;
786 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000787 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000788 Py_INCREF(v);
789 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000790}
791
Martin v. Löwis39195712003-01-04 00:33:13 +0000792PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
793
Martin v. Löwisffad6332002-11-26 09:28:05 +0000794static PyObject*
795get_typename(PyTclObject* obj, void* ignored)
796{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000797 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000798}
799
Martin v. Löwis39195712003-01-04 00:33:13 +0000800
Martin v. Löwisffad6332002-11-26 09:28:05 +0000801static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000802 {"typename", (getter)get_typename, NULL, get_typename__doc__},
803 {"string", (getter)PyTclObject_string, NULL,
804 PyTclObject_string__doc__},
805 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000806};
807
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300808static PyType_Slot PyTclObject_Type_slots[] = {
809 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
810 {Py_tp_repr, (reprfunc)PyTclObject_repr},
811 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200812 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300813 {Py_tp_richcompare, PyTclObject_richcompare},
814 {Py_tp_getset, PyTclObject_getsetlist},
815 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000816};
817
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300818static PyType_Spec PyTclObject_Type_spec = {
819 "_tkinter.Tcl_Obj",
820 sizeof(PyTclObject),
821 0,
822 Py_TPFLAGS_DEFAULT,
823 PyTclObject_Type_slots,
824};
825
826
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000827static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000828AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000829{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000830 Tcl_Obj *result;
831 long longVal;
832 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000833
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000834 if (PyBytes_Check(value))
835 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
836 PyBytes_GET_SIZE(value));
837 else if (PyBool_Check(value))
838 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
839 else if (PyLong_CheckExact(value) &&
840 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
841 !overflow)) {
842 /* If there is an overflow in the long conversion,
843 fall through to default object handling. */
844 return Tcl_NewLongObj(longVal);
845 }
846 else if (PyFloat_Check(value))
847 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
848 else if (PyTuple_Check(value)) {
849 Tcl_Obj **argv = (Tcl_Obj**)
850 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
851 int i;
852 if(!argv)
853 return 0;
854 for(i=0;i<PyTuple_Size(value);i++)
855 argv[i] = AsObj(PyTuple_GetItem(value,i));
856 result = Tcl_NewListObj(PyTuple_Size(value), argv);
857 ckfree(FREECAST argv);
858 return result;
859 }
860 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200861 void *inbuf;
862 Py_ssize_t size;
863 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000864 Tcl_UniChar *outbuf = NULL;
865 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200866 size_t allocsize;
867
868 if (PyUnicode_READY(value) == -1)
869 return NULL;
870
871 inbuf = PyUnicode_DATA(value);
872 size = PyUnicode_GET_LENGTH(value);
873 kind = PyUnicode_KIND(value);
874 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
875 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000876 /* Else overflow occurred, and we take the next exit */
877 if (!outbuf) {
878 PyErr_NoMemory();
879 return NULL;
880 }
881 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200882 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
883 /* We cannot test for sizeof(Tcl_UniChar) directly,
884 so we test for UTF-8 size instead. */
885#if TCL_UTF_MAX == 3
886 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000887 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200888 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100889 "character U+%x is above the range "
890 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100891 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000892 ckfree(FREECAST outbuf);
893 return NULL;
894 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300895#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200896 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000897 }
898 result = Tcl_NewUnicodeObj(outbuf, size);
899 ckfree(FREECAST outbuf);
900 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000901 }
902 else if(PyTclObject_Check(value)) {
903 Tcl_Obj *v = ((PyTclObject*)value)->value;
904 Tcl_IncrRefCount(v);
905 return v;
906 }
907 else {
908 PyObject *v = PyObject_Str(value);
909 if (!v)
910 return 0;
911 result = AsObj(v);
912 Py_DECREF(v);
913 return result;
914 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000915}
916
Martin v. Löwisffad6332002-11-26 09:28:05 +0000917static PyObject*
918FromObj(PyObject* tkapp, Tcl_Obj *value)
919{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000920 PyObject *result = NULL;
921 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000922
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000923 if (value->typePtr == NULL) {
924 return PyUnicode_FromStringAndSize(value->bytes,
925 value->length);
926 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000927
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000928 if (value->typePtr == app->BooleanType) {
929 result = value->internalRep.longValue ? Py_True : Py_False;
930 Py_INCREF(result);
931 return result;
932 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000933
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000934 if (value->typePtr == app->ByteArrayType) {
935 int size;
936 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
937 return PyBytes_FromStringAndSize(data, size);
938 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000939
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000940 if (value->typePtr == app->DoubleType) {
941 return PyFloat_FromDouble(value->internalRep.doubleValue);
942 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000943
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000944 if (value->typePtr == app->IntType) {
945 return PyLong_FromLong(value->internalRep.longValue);
946 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000947
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000948 if (value->typePtr == app->ListType) {
949 int size;
950 int i, status;
951 PyObject *elem;
952 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000953
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000954 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
955 if (status == TCL_ERROR)
956 return Tkinter_Error(tkapp);
957 result = PyTuple_New(size);
958 if (!result)
959 return NULL;
960 for (i = 0; i < size; i++) {
961 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
962 value, i, &tcl_elem);
963 if (status == TCL_ERROR) {
964 Py_DECREF(result);
965 return Tkinter_Error(tkapp);
966 }
967 elem = FromObj(tkapp, tcl_elem);
968 if (!elem) {
969 Py_DECREF(result);
970 return NULL;
971 }
972 PyTuple_SetItem(result, i, elem);
973 }
974 return result;
975 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000976
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000977 if (value->typePtr == app->ProcBodyType) {
978 /* fall through: return tcl object. */
979 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000980
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000981 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200982#if TCL_UTF_MAX==3
983 return PyUnicode_FromKindAndData(
984 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
985 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000986#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200987 return PyUnicode_FromKindAndData(
988 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
989 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000990#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000991 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000992
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000993 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000994}
995
Benjamin Peterson5879d412009-03-30 14:51:56 +0000996#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000997/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000998TCL_DECLARE_MUTEX(call_mutex)
999
1000typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001001 Tcl_Event ev; /* Must be first */
1002 TkappObject *self;
1003 PyObject *args;
1004 int flags;
1005 PyObject **res;
1006 PyObject **exc_type, **exc_value, **exc_tb;
1007 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001008} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001009#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001010
1011void
1012Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001013{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001014 int i;
1015 for (i = 0; i < objc; i++)
1016 Tcl_DecrRefCount(objv[i]);
1017 if (objv != objStore)
1018 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001019}
Guido van Rossum18468821994-06-20 07:49:28 +00001020
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001021/* Convert Python objects to Tcl objects. This must happen in the
1022 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001023
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001024static Tcl_Obj**
1025Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1026{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001027 Tcl_Obj **objv = objStore;
1028 int objc = 0, i;
1029 if (args == NULL)
1030 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001031
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001032 else if (!PyTuple_Check(args)) {
1033 objv[0] = AsObj(args);
1034 if (objv[0] == 0)
1035 goto finally;
1036 objc = 1;
1037 Tcl_IncrRefCount(objv[0]);
1038 }
1039 else {
1040 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001041
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001042 if (objc > ARGSZ) {
1043 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1044 if (objv == NULL) {
1045 PyErr_NoMemory();
1046 objc = 0;
1047 goto finally;
1048 }
1049 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001051 for (i = 0; i < objc; i++) {
1052 PyObject *v = PyTuple_GetItem(args, i);
1053 if (v == Py_None) {
1054 objc = i;
1055 break;
1056 }
1057 objv[i] = AsObj(v);
1058 if (!objv[i]) {
1059 /* Reset objc, so it attempts to clear
1060 objects only up to i. */
1061 objc = i;
1062 goto finally;
1063 }
1064 Tcl_IncrRefCount(objv[i]);
1065 }
1066 }
1067 *pobjc = objc;
1068 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001069finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001070 Tkapp_CallDeallocArgs(objv, objStore, objc);
1071 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001072}
Guido van Rossum212643f1998-04-29 16:22:14 +00001073
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001074/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001075
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001076static PyObject*
1077Tkapp_CallResult(TkappObject *self)
1078{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001079 PyObject *res = NULL;
1080 if(self->wantobjects) {
1081 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1082 /* Not sure whether the IncrRef is necessary, but something
1083 may overwrite the interpreter result while we are
1084 converting it. */
1085 Tcl_IncrRefCount(value);
1086 res = FromObj((PyObject*)self, value);
1087 Tcl_DecrRefCount(value);
1088 } else {
1089 const char *s = Tcl_GetStringResult(self->interp);
1090 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001091
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001092 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1093 }
1094 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001095}
Guido van Rossum632de272000-03-29 00:19:50 +00001096
Benjamin Peterson5879d412009-03-30 14:51:56 +00001097#ifdef WITH_THREAD
1098
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001099/* Tkapp_CallProc is the event procedure that is executed in the context of
1100 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1101 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001102
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001103static int
1104Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1105{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001106 Tcl_Obj *objStore[ARGSZ];
1107 Tcl_Obj **objv;
1108 int objc;
1109 int i;
1110 ENTER_PYTHON
1111 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1112 if (!objv) {
1113 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1114 *(e->res) = NULL;
1115 }
1116 LEAVE_PYTHON
1117 if (!objv)
1118 goto done;
1119 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1120 ENTER_PYTHON
1121 if (i == TCL_ERROR) {
1122 *(e->res) = NULL;
1123 *(e->exc_type) = NULL;
1124 *(e->exc_tb) = NULL;
1125 *(e->exc_value) = PyObject_CallFunction(
1126 Tkinter_TclError, "s",
1127 Tcl_GetStringResult(e->self->interp));
1128 }
1129 else {
1130 *(e->res) = Tkapp_CallResult(e->self);
1131 }
1132 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001134 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001135done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001136 /* Wake up calling thread. */
1137 Tcl_MutexLock(&call_mutex);
1138 Tcl_ConditionNotify(e->done);
1139 Tcl_MutexUnlock(&call_mutex);
1140 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001141}
1142
Benjamin Peterson5879d412009-03-30 14:51:56 +00001143#endif
1144
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001145/* This is the main entry point for calling a Tcl command.
1146 It supports three cases, with regard to threading:
1147 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1148 the context of the calling thread.
1149 2. Tcl is threaded, caller of the command is in the interpreter thread:
1150 Execute the command in the calling thread. Since the Tcl lock will
1151 not be used, we can merge that with case 1.
1152 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1153 the interpreter thread. Allocation of Tcl objects needs to occur in the
1154 interpreter thread, so we ship the PyObject* args to the target thread,
1155 and perform processing there. */
1156
1157static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001158Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001159{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001160 Tcl_Obj *objStore[ARGSZ];
1161 Tcl_Obj **objv = NULL;
1162 int objc, i;
1163 PyObject *res = NULL;
1164 TkappObject *self = (TkappObject*)selfptr;
1165 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001166
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001167 /* If args is a single tuple, replace with contents of tuple */
1168 if (1 == PyTuple_Size(args)){
1169 PyObject* item = PyTuple_GetItem(args, 0);
1170 if (PyTuple_Check(item))
1171 args = item;
1172 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001173#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001174 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1175 /* We cannot call the command directly. Instead, we must
1176 marshal the parameters to the interpreter thread. */
1177 Tkapp_CallEvent *ev;
1178 Tcl_Condition cond = NULL;
1179 PyObject *exc_type, *exc_value, *exc_tb;
1180 if (!WaitForMainloop(self))
1181 return NULL;
1182 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1183 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1184 ev->self = self;
1185 ev->args = args;
1186 ev->res = &res;
1187 ev->exc_type = &exc_type;
1188 ev->exc_value = &exc_value;
1189 ev->exc_tb = &exc_tb;
1190 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001191
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001192 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001193
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001194 if (res == NULL) {
1195 if (exc_type)
1196 PyErr_Restore(exc_type, exc_value, exc_tb);
1197 else
1198 PyErr_SetObject(Tkinter_TclError, exc_value);
1199 }
1200 Tcl_ConditionFinalize(&cond);
1201 }
1202 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001203#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001204 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001205
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001206 objv = Tkapp_CallArgs(args, objStore, &objc);
1207 if (!objv)
1208 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001209
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001210 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001212 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001213
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001214 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001215
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001216 if (i == TCL_ERROR)
1217 Tkinter_Error(selfptr);
1218 else
1219 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001220
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001221 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001222
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001223 Tkapp_CallDeallocArgs(objv, objStore, objc);
1224 }
1225 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001226}
1227
1228
1229static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001230Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001231{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001232 char *script;
1233 PyObject *res = NULL;
1234 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001236 if (!PyArg_ParseTuple(args, "s:eval", &script))
1237 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001239 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001240
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001241 ENTER_TCL
1242 err = Tcl_Eval(Tkapp_Interp(self), script);
1243 ENTER_OVERLAP
1244 if (err == TCL_ERROR)
1245 res = Tkinter_Error(self);
1246 else
1247 res = PyUnicode_FromString(Tkapp_Result(self));
1248 LEAVE_OVERLAP_TCL
1249 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001250}
1251
1252static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001253Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001254{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001255 char *fileName;
1256 PyObject *res = NULL;
1257 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001258
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001259 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1260 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001262 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001263
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001264 ENTER_TCL
1265 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1266 ENTER_OVERLAP
1267 if (err == TCL_ERROR)
1268 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001270 else
1271 res = PyUnicode_FromString(Tkapp_Result(self));
1272 LEAVE_OVERLAP_TCL
1273 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001274}
1275
1276static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001277Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001278{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001279 char *script;
1280 PyObject *res = NULL;
1281 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001282
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001283 if (!PyArg_ParseTuple(args, "s", &script))
1284 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001285
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001286 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001287
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001288 ENTER_TCL
1289 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1290 ENTER_OVERLAP
1291 if (err == TCL_ERROR)
1292 res = Tkinter_Error(self);
1293 else
1294 res = PyUnicode_FromString(Tkapp_Result(self));
1295 LEAVE_OVERLAP_TCL
1296 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001297}
1298
1299static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001300Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001301{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001302 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001303
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001304 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1305 return NULL;
1306 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001307
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001308 ENTER_TCL
1309 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1310 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001311
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001312 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001313}
1314
Barry Warsawfa701a81997-01-16 00:15:11 +00001315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001316
Guido van Rossum18468821994-06-20 07:49:28 +00001317/** Tcl Variable **/
1318
Benjamin Peterson5879d412009-03-30 14:51:56 +00001319typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1320
1321#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001322TCL_DECLARE_MUTEX(var_mutex)
1323
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001324typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 Tcl_Event ev; /* must be first */
1326 PyObject *self;
1327 PyObject *args;
1328 int flags;
1329 EventFunc func;
1330 PyObject **res;
1331 PyObject **exc_type;
1332 PyObject **exc_val;
1333 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001334} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001335#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001336
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001337static int
1338varname_converter(PyObject *in, void *_out)
1339{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001340 char **out = (char**)_out;
1341 if (PyBytes_Check(in)) {
1342 *out = PyBytes_AsString(in);
1343 return 1;
1344 }
1345 if (PyUnicode_Check(in)) {
1346 *out = _PyUnicode_AsString(in);
1347 return 1;
1348 }
1349 if (PyTclObject_Check(in)) {
1350 *out = PyTclObject_TclString(in);
1351 return 1;
1352 }
1353 /* XXX: Should give diagnostics. */
1354 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001355}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001356
Benjamin Peterson5879d412009-03-30 14:51:56 +00001357#ifdef WITH_THREAD
1358
Martin v. Löwis59683e82008-06-13 07:50:45 +00001359static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001360var_perform(VarEvent *ev)
1361{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001362 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1363 if (!*(ev->res)) {
1364 PyObject *exc, *val, *tb;
1365 PyErr_Fetch(&exc, &val, &tb);
1366 PyErr_NormalizeException(&exc, &val, &tb);
1367 *(ev->exc_type) = exc;
1368 *(ev->exc_val) = val;
1369 Py_DECREF(tb);
1370 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001371
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001372}
1373
1374static int
1375var_proc(VarEvent* ev, int flags)
1376{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001377 ENTER_PYTHON
1378 var_perform(ev);
1379 Tcl_MutexLock(&var_mutex);
1380 Tcl_ConditionNotify(ev->cond);
1381 Tcl_MutexUnlock(&var_mutex);
1382 LEAVE_PYTHON
1383 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001384}
1385
Benjamin Peterson5879d412009-03-30 14:51:56 +00001386#endif
1387
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001388static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001389var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001390{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001391#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001392 TkappObject *self = (TkappObject*)selfptr;
1393 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1394 TkappObject *self = (TkappObject*)selfptr;
1395 VarEvent *ev;
1396 PyObject *res, *exc_type, *exc_val;
1397 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001398
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001399 /* The current thread is not the interpreter thread. Marshal
1400 the call to the interpreter thread, then wait for
1401 completion. */
1402 if (!WaitForMainloop(self))
1403 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001405 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001407 ev->self = selfptr;
1408 ev->args = args;
1409 ev->flags = flags;
1410 ev->func = func;
1411 ev->res = &res;
1412 ev->exc_type = &exc_type;
1413 ev->exc_val = &exc_val;
1414 ev->cond = &cond;
1415 ev->ev.proc = (Tcl_EventProc*)var_proc;
1416 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1417 Tcl_ConditionFinalize(&cond);
1418 if (!res) {
1419 PyErr_SetObject(exc_type, exc_val);
1420 Py_DECREF(exc_type);
1421 Py_DECREF(exc_val);
1422 return NULL;
1423 }
1424 return res;
1425 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001426#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001427 /* Tcl is not threaded, or this is the interpreter thread. */
1428 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001429}
1430
Guido van Rossum18468821994-06-20 07:49:28 +00001431static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001432SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001433{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001434 char *name1, *name2;
1435 PyObject *newValue;
1436 PyObject *res = NULL;
1437 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001438
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001439 if (PyArg_ParseTuple(args, "O&O:setvar",
1440 varname_converter, &name1, &newValue)) {
1441 /* XXX Acquire tcl lock??? */
1442 newval = AsObj(newValue);
1443 if (newval == NULL)
1444 return NULL;
1445 ENTER_TCL
1446 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1447 newval, flags);
1448 ENTER_OVERLAP
1449 if (!ok)
1450 Tkinter_Error(self);
1451 else {
1452 res = Py_None;
1453 Py_INCREF(res);
1454 }
1455 LEAVE_OVERLAP_TCL
1456 }
1457 else {
1458 PyErr_Clear();
1459 if (PyArg_ParseTuple(args, "ssO:setvar",
1460 &name1, &name2, &newValue)) {
1461 /* XXX must hold tcl lock already??? */
1462 newval = AsObj(newValue);
1463 ENTER_TCL
1464 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1465 ENTER_OVERLAP
1466 if (!ok)
1467 Tkinter_Error(self);
1468 else {
1469 res = Py_None;
1470 Py_INCREF(res);
1471 }
1472 LEAVE_OVERLAP_TCL
1473 }
1474 else {
1475 return NULL;
1476 }
1477 }
1478 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001479}
1480
1481static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001482Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001483{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001485}
1486
1487static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001488Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001489{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001490 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001491}
1492
Barry Warsawfa701a81997-01-16 00:15:11 +00001493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001494
Guido van Rossum18468821994-06-20 07:49:28 +00001495static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001496GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001497{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001498 char *name1, *name2=NULL;
1499 PyObject *res = NULL;
1500 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001501
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001502 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1503 varname_converter, &name1, &name2))
1504 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001506 ENTER_TCL
1507 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1508 ENTER_OVERLAP
1509 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001510 PyErr_SetString(Tkinter_TclError,
1511 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001512 } else {
1513 if (((TkappObject*)self)->wantobjects) {
1514 res = FromObj(self, tres);
1515 }
1516 else {
1517 res = PyUnicode_FromString(Tcl_GetString(tres));
1518 }
1519 }
1520 LEAVE_OVERLAP_TCL
1521 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001522}
1523
1524static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001525Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001526{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001527 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001528}
1529
1530static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001531Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001532{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001534}
1535
Barry Warsawfa701a81997-01-16 00:15:11 +00001536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001537
Guido van Rossum18468821994-06-20 07:49:28 +00001538static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001539UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001540{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541 char *name1, *name2=NULL;
1542 int code;
1543 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001544
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001545 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1546 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001548 ENTER_TCL
1549 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1550 ENTER_OVERLAP
1551 if (code == TCL_ERROR)
1552 res = Tkinter_Error(self);
1553 else {
1554 Py_INCREF(Py_None);
1555 res = Py_None;
1556 }
1557 LEAVE_OVERLAP_TCL
1558 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001559}
1560
1561static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001562Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001563{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001564 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001565}
1566
1567static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001568Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001569{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001570 return var_invoke(UnsetVar, self, args,
1571 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001572}
1573
Barry Warsawfa701a81997-01-16 00:15:11 +00001574
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001575
Guido van Rossum18468821994-06-20 07:49:28 +00001576/** Tcl to Python **/
1577
1578static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001579Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001580{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001581 char *s;
1582 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001583
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001584 if (PyTuple_Size(args) == 1) {
1585 PyObject* o = PyTuple_GetItem(args, 0);
1586 if (PyLong_Check(o)) {
1587 Py_INCREF(o);
1588 return o;
1589 }
1590 }
1591 if (!PyArg_ParseTuple(args, "s:getint", &s))
1592 return NULL;
1593 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1594 return Tkinter_Error(self);
1595 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001596}
1597
1598static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001599Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001600{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001601 char *s;
1602 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001603
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001604 if (PyTuple_Size(args) == 1) {
1605 PyObject *o = PyTuple_GetItem(args, 0);
1606 if (PyFloat_Check(o)) {
1607 Py_INCREF(o);
1608 return o;
1609 }
1610 }
1611 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1612 return NULL;
1613 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1614 return Tkinter_Error(self);
1615 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001616}
1617
1618static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001619Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001620{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001621 char *s;
1622 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001623
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001624 if (PyTuple_Size(args) == 1) {
1625 PyObject *o = PyTuple_GetItem(args, 0);
1626 if (PyLong_Check(o)) {
1627 Py_INCREF(o);
1628 return o;
1629 }
1630 }
1631 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1632 return NULL;
1633 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1634 return Tkinter_Error(self);
1635 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001636}
1637
1638static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001639Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001640{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001641 char *s;
1642 PyObject *res = NULL;
1643 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001645 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1646 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001648 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001650 ENTER_TCL
1651 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1652 ENTER_OVERLAP
1653 if (retval == TCL_ERROR)
1654 res = Tkinter_Error(self);
1655 else
1656 res = Py_BuildValue("s", Tkapp_Result(self));
1657 LEAVE_OVERLAP_TCL
1658 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001659}
1660
1661static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001662Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001663{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001664 char *s;
1665 PyObject *res = NULL;
1666 int retval;
1667 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001669 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1670 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001672 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001674 ENTER_TCL
1675 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1676 ENTER_OVERLAP
1677 if (retval == TCL_ERROR)
1678 res = Tkinter_Error(self);
1679 else
1680 res = Py_BuildValue("l", v);
1681 LEAVE_OVERLAP_TCL
1682 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001683}
1684
1685static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001686Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001687{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001688 char *s;
1689 PyObject *res = NULL;
1690 double v;
1691 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001692
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001693 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1694 return NULL;
1695 CHECK_TCL_APPARTMENT;
1696 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1697 ENTER_TCL
1698 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1699 ENTER_OVERLAP
1700 PyFPE_END_PROTECT(retval)
1701 if (retval == TCL_ERROR)
1702 res = Tkinter_Error(self);
1703 else
1704 res = Py_BuildValue("d", v);
1705 LEAVE_OVERLAP_TCL
1706 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001707}
1708
1709static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001710Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001711{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001712 char *s;
1713 PyObject *res = NULL;
1714 int retval;
1715 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001717 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1718 return NULL;
1719 CHECK_TCL_APPARTMENT;
1720 ENTER_TCL
1721 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1722 ENTER_OVERLAP
1723 if (retval == TCL_ERROR)
1724 res = Tkinter_Error(self);
1725 else
1726 res = Py_BuildValue("i", v);
1727 LEAVE_OVERLAP_TCL
1728 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001729}
1730
Barry Warsawfa701a81997-01-16 00:15:11 +00001731
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001732
Guido van Rossum18468821994-06-20 07:49:28 +00001733static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001734Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001735{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001736 char *list;
1737 int argc;
1738 char **argv;
1739 PyObject *v;
1740 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001741
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001742 if (PyTuple_Size(args) == 1) {
1743 v = PyTuple_GetItem(args, 0);
1744 if (PyTuple_Check(v)) {
1745 Py_INCREF(v);
1746 return v;
1747 }
1748 }
1749 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1750 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001751
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001752 if (Tcl_SplitList(Tkapp_Interp(self), list,
1753 &argc, &argv) == TCL_ERROR) {
1754 PyMem_Free(list);
1755 return Tkinter_Error(self);
1756 }
Guido van Rossum18468821994-06-20 07:49:28 +00001757
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001758 if (!(v = PyTuple_New(argc)))
1759 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001760
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001761 for (i = 0; i < argc; i++) {
1762 PyObject *s = PyUnicode_FromString(argv[i]);
1763 if (!s || PyTuple_SetItem(v, i, s)) {
1764 Py_DECREF(v);
1765 v = NULL;
1766 goto finally;
1767 }
1768 }
Guido van Rossum18468821994-06-20 07:49:28 +00001769
Barry Warsawfa701a81997-01-16 00:15:11 +00001770 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001771 ckfree(FREECAST argv);
1772 PyMem_Free(list);
1773 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001774}
1775
1776static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001777Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001778{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001779 PyObject *v;
1780 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001781
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001782 if (PyTuple_Size(args) == 1) {
1783 PyObject* o = PyTuple_GetItem(args, 0);
1784 if (PyTuple_Check(o)) {
1785 o = SplitObj(o);
1786 return o;
1787 }
1788 }
1789 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1790 return NULL;
1791 v = Split(list);
1792 PyMem_Free(list);
1793 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001794}
1795
Barry Warsawfa701a81997-01-16 00:15:11 +00001796
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001797
Guido van Rossum18468821994-06-20 07:49:28 +00001798/** Tcl Command **/
1799
Guido van Rossum00d93061998-05-28 23:06:38 +00001800/* Client data struct */
1801typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001802 PyObject *self;
1803 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001804} PythonCmd_ClientData;
1805
1806static int
Fred Drake509d79a2000-07-08 04:04:38 +00001807PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001808{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001809 errorInCmd = 1;
1810 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1811 LEAVE_PYTHON
1812 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001813}
1814
Guido van Rossum18468821994-06-20 07:49:28 +00001815/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001816 * function or method.
1817 */
Guido van Rossum18468821994-06-20 07:49:28 +00001818static int
Fred Drake509d79a2000-07-08 04:04:38 +00001819PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001820{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001821 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001822 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001823 int i, rv;
1824 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001825
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001826 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001827
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001828 /* TBD: no error checking here since we know, via the
1829 * Tkapp_CreateCommand() that the client data is a two-tuple
1830 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001831 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001832
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001833 /* Create argument list (argv1, ..., argvN) */
1834 if (!(arg = PyTuple_New(argc - 1)))
1835 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001837 for (i = 0; i < (argc - 1); i++) {
1838 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04001839 if (!s) {
1840 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
1841 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
1842 !strcmp(argv[i + 1], "\xC0\x80")) {
1843 PyErr_Clear();
1844 /* Convert to "strict" utf-8 null */
1845 s = PyUnicode_FromString("\0");
1846 } else {
1847 Py_DECREF(arg);
1848 return PythonCmd_Error(interp);
1849 }
1850 }
1851 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001852 Py_DECREF(arg);
1853 return PythonCmd_Error(interp);
1854 }
1855 }
1856 res = PyEval_CallObject(func, arg);
1857 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001858
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001859 if (res == NULL)
1860 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001861
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001862 obj_res = AsObj(res);
1863 if (obj_res == NULL) {
1864 Py_DECREF(res);
1865 return PythonCmd_Error(interp);
1866 }
1867 else {
1868 Tcl_SetObjResult(interp, obj_res);
1869 rv = TCL_OK;
1870 }
Guido van Rossum2834b972000-10-06 16:58:26 +00001871
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001872 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001873
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001874 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001876 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001877}
1878
1879static void
Fred Drake509d79a2000-07-08 04:04:38 +00001880PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001881{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001882 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00001883
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001884 ENTER_PYTHON
1885 Py_XDECREF(data->self);
1886 Py_XDECREF(data->func);
1887 PyMem_DEL(data);
1888 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001889}
1890
Barry Warsawfa701a81997-01-16 00:15:11 +00001891
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001892
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001893
Benjamin Peterson5879d412009-03-30 14:51:56 +00001894#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001895TCL_DECLARE_MUTEX(command_mutex)
1896
1897typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001898 Tcl_Event ev;
1899 Tcl_Interp* interp;
1900 char *name;
1901 int create;
1902 int *status;
1903 ClientData *data;
1904 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001905} CommandEvent;
1906
1907static int
1908Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001909{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001910 if (ev->create)
1911 *ev->status = Tcl_CreateCommand(
1912 ev->interp, ev->name, PythonCmd,
1913 ev->data, PythonCmdDelete) == NULL;
1914 else
1915 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1916 Tcl_MutexLock(&command_mutex);
1917 Tcl_ConditionNotify(ev->done);
1918 Tcl_MutexUnlock(&command_mutex);
1919 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001920}
Benjamin Peterson5879d412009-03-30 14:51:56 +00001921#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001922
1923static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001924Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001925{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001926 TkappObject *self = (TkappObject*)selfptr;
1927 PythonCmd_ClientData *data;
1928 char *cmdName;
1929 PyObject *func;
1930 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001931
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001932 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
1933 return NULL;
1934 if (!PyCallable_Check(func)) {
1935 PyErr_SetString(PyExc_TypeError, "command not callable");
1936 return NULL;
1937 }
Guido van Rossum18468821994-06-20 07:49:28 +00001938
Martin v. Löwisa9656492003-03-30 08:44:58 +00001939#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001940 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
1941 !WaitForMainloop(self))
1942 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001943#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001944
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001945 data = PyMem_NEW(PythonCmd_ClientData, 1);
1946 if (!data)
1947 return PyErr_NoMemory();
1948 Py_INCREF(self);
1949 Py_INCREF(func);
1950 data->self = selfptr;
1951 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001952#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001953 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1954 Tcl_Condition cond = NULL;
1955 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
1956 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
1957 ev->interp = self->interp;
1958 ev->create = 1;
1959 ev->name = cmdName;
1960 ev->data = (ClientData)data;
1961 ev->status = &err;
1962 ev->done = &cond;
1963 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
1964 Tcl_ConditionFinalize(&cond);
1965 }
1966 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00001967#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001968 {
1969 ENTER_TCL
1970 err = Tcl_CreateCommand(
1971 Tkapp_Interp(self), cmdName, PythonCmd,
1972 (ClientData)data, PythonCmdDelete) == NULL;
1973 LEAVE_TCL
1974 }
1975 if (err) {
1976 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
1977 PyMem_DEL(data);
1978 return NULL;
1979 }
Guido van Rossum18468821994-06-20 07:49:28 +00001980
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001981 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001982}
1983
Barry Warsawfa701a81997-01-16 00:15:11 +00001984
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001985
Guido van Rossum18468821994-06-20 07:49:28 +00001986static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001987Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001988{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001989 TkappObject *self = (TkappObject*)selfptr;
1990 char *cmdName;
1991 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001992
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001993 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
1994 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001995
1996#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001997 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1998 Tcl_Condition cond = NULL;
1999 CommandEvent *ev;
2000 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2001 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2002 ev->interp = self->interp;
2003 ev->create = 0;
2004 ev->name = cmdName;
2005 ev->status = &err;
2006 ev->done = &cond;
2007 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2008 &command_mutex);
2009 Tcl_ConditionFinalize(&cond);
2010 }
2011 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002012#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002013 {
2014 ENTER_TCL
2015 err = Tcl_DeleteCommand(self->interp, cmdName);
2016 LEAVE_TCL
2017 }
2018 if (err == -1) {
2019 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2020 return NULL;
2021 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002022 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002023}
2024
Barry Warsawfa701a81997-01-16 00:15:11 +00002025
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002026
Guido van Rossum00d93061998-05-28 23:06:38 +00002027#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002028/** File Handler **/
2029
Guido van Rossum00d93061998-05-28 23:06:38 +00002030typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002031 PyObject *func;
2032 PyObject *file;
2033 int id;
2034 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002035} FileHandler_ClientData;
2036
2037static FileHandler_ClientData *HeadFHCD;
2038
2039static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002040NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002041{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002042 FileHandler_ClientData *p;
2043 p = PyMem_NEW(FileHandler_ClientData, 1);
2044 if (p != NULL) {
2045 Py_XINCREF(func);
2046 Py_XINCREF(file);
2047 p->func = func;
2048 p->file = file;
2049 p->id = id;
2050 p->next = HeadFHCD;
2051 HeadFHCD = p;
2052 }
2053 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002054}
2055
2056static void
Fred Drake509d79a2000-07-08 04:04:38 +00002057DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002058{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002059 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002060
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002061 pp = &HeadFHCD;
2062 while ((p = *pp) != NULL) {
2063 if (p->id == id) {
2064 *pp = p->next;
2065 Py_XDECREF(p->func);
2066 Py_XDECREF(p->file);
2067 PyMem_DEL(p);
2068 }
2069 else
2070 pp = &p->next;
2071 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002072}
2073
Guido van Rossuma597dde1995-01-10 20:56:29 +00002074static void
Fred Drake509d79a2000-07-08 04:04:38 +00002075FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002076{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002077 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2078 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002079
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002080 ENTER_PYTHON
2081 func = data->func;
2082 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002083
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002084 arg = Py_BuildValue("(Oi)", file, (long) mask);
2085 res = PyEval_CallObject(func, arg);
2086 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002088 if (res == NULL) {
2089 errorInCmd = 1;
2090 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2091 }
2092 Py_XDECREF(res);
2093 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002094}
2095
Guido van Rossum18468821994-06-20 07:49:28 +00002096static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002097Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2098 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002099{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002100 FileHandler_ClientData *data;
2101 PyObject *file, *func;
2102 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002104 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2105 &file, &mask, &func))
2106 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002107
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002108 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002109
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002110 tfile = PyObject_AsFileDescriptor(file);
2111 if (tfile < 0)
2112 return NULL;
2113 if (!PyCallable_Check(func)) {
2114 PyErr_SetString(PyExc_TypeError, "bad argument list");
2115 return NULL;
2116 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002118 data = NewFHCD(func, file, tfile);
2119 if (data == NULL)
2120 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002121
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002122 /* Ought to check for null Tcl_File object... */
2123 ENTER_TCL
2124 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2125 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002126 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002127}
2128
2129static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002130Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002131{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002132 PyObject *file;
2133 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002134
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002135 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2136 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002137
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002139
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002140 tfile = PyObject_AsFileDescriptor(file);
2141 if (tfile < 0)
2142 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002143
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002144 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002145
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002146 /* Ought to check for null Tcl_File object... */
2147 ENTER_TCL
2148 Tcl_DeleteFileHandler(tfile);
2149 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002150 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002151}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002152#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002153
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002154
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002155/**** Tktt Object (timer token) ****/
2156
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002157static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002158
Guido van Rossum00d93061998-05-28 23:06:38 +00002159typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 PyObject_HEAD
2161 Tcl_TimerToken token;
2162 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002163} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002164
2165static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002166Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002167{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002168 TkttObject *v = (TkttObject *)self;
2169 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002170
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002171 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2172 return NULL;
2173 if (v->token != NULL) {
2174 Tcl_DeleteTimerHandler(v->token);
2175 v->token = NULL;
2176 }
2177 if (func != NULL) {
2178 v->func = NULL;
2179 Py_DECREF(func);
2180 Py_DECREF(v); /* See Tktt_New() */
2181 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002182 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002183}
2184
2185static PyMethodDef Tktt_methods[] =
2186{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002187 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2188 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002189};
2190
2191static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002192Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002193{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002194 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002195
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002196 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 if (v == NULL)
2198 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002199
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002200 Py_INCREF(func);
2201 v->token = NULL;
2202 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002203
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002204 /* Extra reference, deleted when called or when handler is deleted */
2205 Py_INCREF(v);
2206 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002207}
2208
2209static void
Fred Drake509d79a2000-07-08 04:04:38 +00002210Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002211{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002212 TkttObject *v = (TkttObject *)self;
2213 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002214
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002215 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002216
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002217 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002218}
2219
Guido van Rossum597ac201998-05-12 14:36:19 +00002220static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002221Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002222{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002223 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002224 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2225 v,
2226 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002227}
2228
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002229static PyType_Slot Tktt_Type_slots[] = {
2230 {Py_tp_dealloc, Tktt_Dealloc},
2231 {Py_tp_repr, Tktt_Repr},
2232 {Py_tp_methods, Tktt_methods},
2233 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002234};
2235
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002236static PyType_Spec Tktt_Type_spec = {
2237 "tktimertoken",
2238 sizeof(TkttObject),
2239 0,
2240 Py_TPFLAGS_DEFAULT,
2241 Tktt_Type_slots,
2242};
Barry Warsawfa701a81997-01-16 00:15:11 +00002243
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002244
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002245/** Timer Handler **/
2246
2247static void
Fred Drake509d79a2000-07-08 04:04:38 +00002248TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002249{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002250 TkttObject *v = (TkttObject *)clientData;
2251 PyObject *func = v->func;
2252 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002253
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002254 if (func == NULL)
2255 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002257 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002258
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002259 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002261 res = PyEval_CallObject(func, NULL);
2262 Py_DECREF(func);
2263 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002264
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002265 if (res == NULL) {
2266 errorInCmd = 1;
2267 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2268 }
2269 else
2270 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002271
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002272 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002273}
2274
2275static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002276Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002277{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002278 int milliseconds;
2279 PyObject *func;
2280 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002282 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2283 &milliseconds, &func))
2284 return NULL;
2285 if (!PyCallable_Check(func)) {
2286 PyErr_SetString(PyExc_TypeError, "bad argument list");
2287 return NULL;
2288 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002289
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002290 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002291
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002292 v = Tktt_New(func);
2293 if (v) {
2294 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2295 (ClientData)v);
2296 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002298 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002299}
2300
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002301
Guido van Rossum18468821994-06-20 07:49:28 +00002302/** Event Loop **/
2303
Guido van Rossum18468821994-06-20 07:49:28 +00002304static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002305Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002306{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002307 int threshold = 0;
2308 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002309#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002310 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002311#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002313 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2314 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002316 CHECK_TCL_APPARTMENT;
2317 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002318
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002319 quitMainLoop = 0;
2320 while (Tk_GetNumMainWindows() > threshold &&
2321 !quitMainLoop &&
2322 !errorInCmd)
2323 {
2324 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002325
2326#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002327 if (self->threaded) {
2328 /* Allow other Python threads to run. */
2329 ENTER_TCL
2330 result = Tcl_DoOneEvent(0);
2331 LEAVE_TCL
2332 }
2333 else {
2334 Py_BEGIN_ALLOW_THREADS
2335 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2336 tcl_tstate = tstate;
2337 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2338 tcl_tstate = NULL;
2339 if(tcl_lock)PyThread_release_lock(tcl_lock);
2340 if (result == 0)
2341 Sleep(Tkinter_busywaitinterval);
2342 Py_END_ALLOW_THREADS
2343 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002344#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002345 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002346#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002348 if (PyErr_CheckSignals() != 0) {
2349 self->dispatching = 0;
2350 return NULL;
2351 }
2352 if (result < 0)
2353 break;
2354 }
2355 self->dispatching = 0;
2356 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002357
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002358 if (errorInCmd) {
2359 errorInCmd = 0;
2360 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2361 excInCmd = valInCmd = trbInCmd = NULL;
2362 return NULL;
2363 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002364 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002365}
2366
2367static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002368Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002369{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002370 int flags = 0;
2371 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002373 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2374 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002376 ENTER_TCL
2377 rv = Tcl_DoOneEvent(flags);
2378 LEAVE_TCL
2379 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002380}
2381
2382static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002383Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002384{
2385
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002386 if (!PyArg_ParseTuple(args, ":quit"))
2387 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002389 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002390 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002391}
2392
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002393static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002394Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002395{
2396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002397 if (!PyArg_ParseTuple(args, ":interpaddr"))
2398 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002399
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002400 return PyLong_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002401}
2402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002403static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002404Tkapp_TkInit(PyObject *self, PyObject *args)
2405{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002406 Tcl_Interp *interp = Tkapp_Interp(self);
2407 const char * _tk_exists = NULL;
2408 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002409
Guilherme Polob681df42009-02-09 22:33:59 +00002410#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002411 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2412 * first call failed.
2413 * To avoid the deadlock, we just refuse the second call through
2414 * a static variable.
2415 */
2416 if (tk_load_failed) {
2417 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2418 return NULL;
2419 }
Guilherme Polob681df42009-02-09 22:33:59 +00002420#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002421
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002422 /* We want to guard against calling Tk_Init() multiple times */
2423 CHECK_TCL_APPARTMENT;
2424 ENTER_TCL
2425 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2426 ENTER_OVERLAP
2427 if (err == TCL_ERROR) {
2428 /* This sets an exception, but we cannot return right
2429 away because we need to exit the overlap first. */
2430 Tkinter_Error(self);
2431 } else {
2432 _tk_exists = Tkapp_Result(self);
2433 }
2434 LEAVE_OVERLAP_TCL
2435 if (err == TCL_ERROR) {
2436 return NULL;
2437 }
2438 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2439 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002440 PyErr_SetString(Tkinter_TclError,
2441 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002442#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002443 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002444#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002445 return NULL;
2446 }
2447 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002448 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002449}
Barry Warsawfa701a81997-01-16 00:15:11 +00002450
Martin v. Löwisffad6332002-11-26 09:28:05 +00002451static PyObject *
2452Tkapp_WantObjects(PyObject *self, PyObject *args)
2453{
2454
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002455 int wantobjects = -1;
2456 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2457 return NULL;
2458 if (wantobjects == -1)
2459 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2460 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002461
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002462 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002463}
2464
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002465static PyObject *
2466Tkapp_WillDispatch(PyObject *self, PyObject *args)
2467{
2468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002469 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002470
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002471 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002472}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002474
Guido van Rossum18468821994-06-20 07:49:28 +00002475/**** Tkapp Method List ****/
2476
2477static PyMethodDef Tkapp_methods[] =
2478{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002479 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2480 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2481 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002482 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002483 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2484 {"record", Tkapp_Record, METH_VARARGS},
2485 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2486 {"setvar", Tkapp_SetVar, METH_VARARGS},
2487 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2488 {"getvar", Tkapp_GetVar, METH_VARARGS},
2489 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2490 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2491 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2492 {"getint", Tkapp_GetInt, METH_VARARGS},
2493 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2494 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2495 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2496 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2497 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2498 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2499 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2500 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002501 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2502 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002503#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002504 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2505 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002506#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002507 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2508 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2509 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2510 {"quit", Tkapp_Quit, METH_VARARGS},
2511 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2512 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2513 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002514};
2515
Barry Warsawfa701a81997-01-16 00:15:11 +00002516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002517
Guido van Rossum18468821994-06-20 07:49:28 +00002518/**** Tkapp Type Methods ****/
2519
2520static void
Fred Drake509d79a2000-07-08 04:04:38 +00002521Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002522{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002523 /*CHECK_TCL_APPARTMENT;*/
2524 ENTER_TCL
2525 Tcl_DeleteInterp(Tkapp_Interp(self));
2526 LEAVE_TCL
2527 PyObject_Del(self);
2528 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002529}
2530
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002531static PyType_Slot Tkapp_Type_slots[] = {
2532 {Py_tp_dealloc, Tkapp_Dealloc},
2533 {Py_tp_methods, Tkapp_methods},
2534 {0, 0}
2535};
2536
2537
2538static PyType_Spec Tkapp_Type_spec = {
2539 "tkapp",
2540 sizeof(TkappObject),
2541 0,
2542 Py_TPFLAGS_DEFAULT,
2543 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002544};
2545
Barry Warsawfa701a81997-01-16 00:15:11 +00002546
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002547
Guido van Rossum18468821994-06-20 07:49:28 +00002548/**** Tkinter Module ****/
2549
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002550typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002551 PyObject* tuple;
2552 int size; /* current size */
2553 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002554} FlattenContext;
2555
2556static int
2557_bump(FlattenContext* context, int size)
2558{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002559 /* expand tuple to hold (at least) size new items.
2560 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002561
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002562 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002564 if (maxsize < context->size + size)
2565 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002567 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002568
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002569 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002570}
2571
2572static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002573_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002574{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002575 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002576
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002577 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579 if (depth > 1000) {
2580 PyErr_SetString(PyExc_ValueError,
2581 "nesting too deep in _flatten");
2582 return 0;
2583 } else if (PyList_Check(item)) {
2584 size = PyList_GET_SIZE(item);
2585 /* preallocate (assume no nesting) */
2586 if (context->size + size > context->maxsize &&
2587 !_bump(context, size))
2588 return 0;
2589 /* copy items to output tuple */
2590 for (i = 0; i < size; i++) {
2591 PyObject *o = PyList_GET_ITEM(item, i);
2592 if (PyList_Check(o) || PyTuple_Check(o)) {
2593 if (!_flatten1(context, o, depth + 1))
2594 return 0;
2595 } else if (o != Py_None) {
2596 if (context->size + 1 > context->maxsize &&
2597 !_bump(context, 1))
2598 return 0;
2599 Py_INCREF(o);
2600 PyTuple_SET_ITEM(context->tuple,
2601 context->size++, o);
2602 }
2603 }
2604 } else if (PyTuple_Check(item)) {
2605 /* same, for tuples */
2606 size = PyTuple_GET_SIZE(item);
2607 if (context->size + size > context->maxsize &&
2608 !_bump(context, size))
2609 return 0;
2610 for (i = 0; i < size; i++) {
2611 PyObject *o = PyTuple_GET_ITEM(item, i);
2612 if (PyList_Check(o) || PyTuple_Check(o)) {
2613 if (!_flatten1(context, o, depth + 1))
2614 return 0;
2615 } else if (o != Py_None) {
2616 if (context->size + 1 > context->maxsize &&
2617 !_bump(context, 1))
2618 return 0;
2619 Py_INCREF(o);
2620 PyTuple_SET_ITEM(context->tuple,
2621 context->size++, o);
2622 }
2623 }
2624 } else {
2625 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2626 return 0;
2627 }
2628 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002629}
2630
2631static PyObject *
2632Tkinter_Flatten(PyObject* self, PyObject* args)
2633{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002634 FlattenContext context;
2635 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002637 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2638 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002639
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002640 context.maxsize = PySequence_Size(item);
2641 if (context.maxsize < 0)
2642 return NULL;
2643 if (context.maxsize == 0)
2644 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002645
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002646 context.tuple = PyTuple_New(context.maxsize);
2647 if (!context.tuple)
2648 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002650 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002651
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002652 if (!_flatten1(&context, item,0))
2653 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002654
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002655 if (_PyTuple_Resize(&context.tuple, context.size))
2656 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002658 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002659}
2660
Guido van Rossum18468821994-06-20 07:49:28 +00002661static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002662Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002663{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002664 char *screenName = NULL;
2665 char *baseName = NULL; /* XXX this is not used anymore;
2666 try getting rid of it. */
2667 char *className = NULL;
2668 int interactive = 0;
2669 int wantobjects = 0;
2670 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2671 int sync = 0; /* pass -sync to wish */
2672 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002674 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2677 &screenName, &baseName, &className,
2678 &interactive, &wantobjects, &wantTk,
2679 &sync, &use))
2680 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002682 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002683 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002684 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002685}
2686
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002687static PyObject *
2688Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2689{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002690 int new_val;
2691 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2692 return NULL;
2693 if (new_val < 0) {
2694 PyErr_SetString(PyExc_ValueError,
2695 "busywaitinterval must be >= 0");
2696 return NULL;
2697 }
2698 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002699 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002700}
2701
2702static char setbusywaitinterval_doc[] =
2703"setbusywaitinterval(n) -> None\n\
2704\n\
2705Set the busy-wait interval in milliseconds between successive\n\
2706calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2707It should be set to a divisor of the maximum time between\n\
2708frames in an animation.";
2709
2710static PyObject *
2711Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2712{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002713 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002714}
2715
2716static char getbusywaitinterval_doc[] =
2717"getbusywaitinterval() -> int\n\
2718\n\
2719Return the current busy-wait interval between successive\n\
2720calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2721
Guido van Rossum18468821994-06-20 07:49:28 +00002722static PyMethodDef moduleMethods[] =
2723{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002724 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2725 {"create", Tkinter_Create, METH_VARARGS},
2726 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2727 setbusywaitinterval_doc},
2728 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2729 METH_NOARGS, getbusywaitinterval_doc},
2730 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002731};
2732
Guido van Rossum7bf15641998-05-22 18:28:17 +00002733#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002734
2735static int stdin_ready = 0;
2736
Guido van Rossumad4db171998-06-13 13:56:28 +00002737#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002738static void
Fred Drake509d79a2000-07-08 04:04:38 +00002739MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002740{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002742}
Guido van Rossumad4db171998-06-13 13:56:28 +00002743#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002744
Martin v. Löwisa9656492003-03-30 08:44:58 +00002745#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002746static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002747#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002748
Guido van Rossum18468821994-06-20 07:49:28 +00002749static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002750EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002751{
Guido van Rossumad4db171998-06-13 13:56:28 +00002752#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002753 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002754#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002755#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002756 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002757#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002758 stdin_ready = 0;
2759 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002760#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002761 tfile = fileno(stdin);
2762 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002763#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002764 while (!errorInCmd && !stdin_ready) {
2765 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002766#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002767 if (_kbhit()) {
2768 stdin_ready = 1;
2769 break;
2770 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002771#endif
2772#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002773 Py_BEGIN_ALLOW_THREADS
2774 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2775 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002776
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002777 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002778
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002779 tcl_tstate = NULL;
2780 if(tcl_lock)PyThread_release_lock(tcl_lock);
2781 if (result == 0)
2782 Sleep(Tkinter_busywaitinterval);
2783 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002784#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002785 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002786#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002787
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002788 if (result < 0)
2789 break;
2790 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002791#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002792 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002793#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 if (errorInCmd) {
2795 errorInCmd = 0;
2796 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2797 excInCmd = valInCmd = trbInCmd = NULL;
2798 PyErr_Print();
2799 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002800#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002801 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002802#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002803 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002804}
Guido van Rossum18468821994-06-20 07:49:28 +00002805
Guido van Rossum00d93061998-05-28 23:06:38 +00002806#endif
2807
Guido van Rossum7bf15641998-05-22 18:28:17 +00002808static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002809EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002810{
Guido van Rossum00d93061998-05-28 23:06:38 +00002811#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002812 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002813#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002814 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002815#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002816 PyOS_InputHook = EventHook;
2817 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002818#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002819}
2820
2821static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002822DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002823{
Guido van Rossum00d93061998-05-28 23:06:38 +00002824#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002825 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2826 PyOS_InputHook = NULL;
2827 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002828#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002829}
2830
Barry Warsawfa701a81997-01-16 00:15:11 +00002831
Martin v. Löwis1a214512008-06-11 05:26:20 +00002832static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002833 PyModuleDef_HEAD_INIT,
2834 "_tkinter",
2835 NULL,
2836 -1,
2837 moduleMethods,
2838 NULL,
2839 NULL,
2840 NULL,
2841 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002842};
2843
Mark Hammond62b1ab12002-07-23 06:31:15 +00002844PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002845PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002846{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002847 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00002848
Guido van Rossum00d93061998-05-28 23:06:38 +00002849#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002850 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002851 if (tcl_lock == NULL)
2852 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002853#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002854
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002855 m = PyModule_Create(&_tkintermodule);
2856 if (m == NULL)
2857 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002858
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002859 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
2860 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02002861 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002862 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02002863 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002864 Py_INCREF(o);
2865 if (PyModule_AddObject(m, "TclError", o)) {
2866 Py_DECREF(o);
2867 Py_DECREF(m);
2868 return NULL;
2869 }
2870 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002871
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002872 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
2873 Py_DECREF(m);
2874 return NULL;
2875 }
2876 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
2877 Py_DECREF(m);
2878 return NULL;
2879 }
2880 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
2881 Py_DECREF(m);
2882 return NULL;
2883 }
2884 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
2885 Py_DECREF(m);
2886 return NULL;
2887 }
2888 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
2889 Py_DECREF(m);
2890 return NULL;
2891 }
2892 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
2893 Py_DECREF(m);
2894 return NULL;
2895 }
2896 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
2897 Py_DECREF(m);
2898 return NULL;
2899 }
2900 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
2901 Py_DECREF(m);
2902 return NULL;
2903 }
2904 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
2905 Py_DECREF(m);
2906 return NULL;
2907 }
2908 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
2909 Py_DECREF(m);
2910 return NULL;
2911 }
2912 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
2913 Py_DECREF(m);
2914 return NULL;
2915 }
2916
2917 o = PyType_FromSpec(&Tkapp_Type_spec);
2918 if (o == NULL) {
2919 Py_DECREF(m);
2920 return NULL;
2921 }
2922 if (PyModule_AddObject(m, "TkappType", o)) {
2923 Py_DECREF(o);
2924 Py_DECREF(m);
2925 return NULL;
2926 }
2927 Tkapp_Type = o;
2928
2929 o = PyType_FromSpec(&Tktt_Type_spec);
2930 if (o == NULL) {
2931 Py_DECREF(m);
2932 return NULL;
2933 }
2934 if (PyModule_AddObject(m, "TkttType", o)) {
2935 Py_DECREF(o);
2936 Py_DECREF(m);
2937 return NULL;
2938 }
2939 Tktt_Type = o;
2940
2941 o = PyType_FromSpec(&PyTclObject_Type_spec);
2942 if (o == NULL) {
2943 Py_DECREF(m);
2944 return NULL;
2945 }
2946 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
2947 Py_DECREF(o);
2948 Py_DECREF(m);
2949 return NULL;
2950 }
2951 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00002952
2953#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002954 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2955 * start waking up. Note that Tcl_FindExecutable will do this, this
2956 * code must be above it! The original warning from
2957 * tkMacOSXAppInit.c is copied below.
2958 *
2959 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2960 * Tcl interpreter for now. It probably should work to do this
2961 * in the other order, but for now it doesn't seem to.
2962 *
2963 */
2964 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00002965#endif
2966
2967
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002968 /* This helps the dynamic loader; in Unicode aware Tcl versions
2969 it also helps Tcl find its encodings. */
2970 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
2971 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00002972 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002973 if (cexe)
2974 Tcl_FindExecutable(PyBytes_AsString(cexe));
2975 Py_XDECREF(cexe);
2976 Py_DECREF(uexe);
2977 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00002978
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002979 if (PyErr_Occurred()) {
2980 Py_DECREF(m);
2981 return NULL;
2982 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002983
Guido van Rossum43ff8681998-07-14 18:02:13 +00002984#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002985 /* This was not a good idea; through <Destroy> bindings,
2986 Tcl_Finalize() may invoke Python code but at that point the
2987 interpreter and thread state have already been destroyed! */
2988 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002989#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002990 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00002991}