blob: 52ee881373f2b78f6c00182d870c8cf0afda22e3 [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 Pitrouc83ea132010-05-09 14:46:46 +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
47#define PyBool_FromLong PyInt_FromLong
48#endif
49
Serhiy Storchaka42035702013-08-21 21:46:12 +030050#define CHECK_SIZE(size, elemsize) \
51 ((size_t)(size) <= (size_t)INT_MAX && \
52 (size_t)(size) <= UINT_MAX / (size_t)(elemsize))
53
Martin v. Löwis71e25a02002-10-01 18:08:06 +000054/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
55 making _tkinter correct for this API means to break earlier
56 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
57 earlier versions. Once Tcl releases before 8.4 don't need to be supported
58 anymore, this should go. */
59#define USE_COMPAT_CONST
60
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000061/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
62 it always; if Tcl is not threaded, the thread functions in
63 Tcl are empty. */
64#define TCL_THREADS
65
Jack Jansencb852442001-12-09 23:15:56 +000066#ifdef TK_FRAMEWORK
67#include <Tcl/tcl.h>
68#include <Tk/tk.h>
69#else
Guido van Rossum18468821994-06-20 07:49:28 +000070#include <tcl.h>
71#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000072#endif
Guido van Rossum18468821994-06-20 07:49:28 +000073
Guilherme Polo5d64c332009-04-05 02:11:19 +000074#include "tkinter.h"
75
Jason Tishlerbbe89612002-12-31 20:30:46 +000076/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000077#ifndef CONST84_RETURN
78#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000079#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000080#define CONST
81#endif
82
Guilherme Poloc5eba1e2009-02-09 20:57:45 +000083#if TK_VERSION_HEX < 0x08030102
84#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000085#endif
86
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000087/* Unicode conversion assumes that Tcl_UniChar is two bytes.
88 We cannot test this directly, so we test UTF-8 size instead,
89 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Antoine Pitrouc83ea132010-05-09 14:46:46 +000090 either UTF-16 or UCS-4.
91 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000092 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
93 as well.
94*/
95#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000096#error "unsupported Tcl configuration"
97#endif
98
Jack Janseneddc1442003-11-20 01:44:59 +000099#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000100#define HAVE_CREATEFILEHANDLER
101#endif
102
Guido van Rossum00d93061998-05-28 23:06:38 +0000103#ifdef HAVE_CREATEFILEHANDLER
104
Neal Norwitzd948a432006-01-08 01:08:55 +0000105/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
106 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
107#ifndef TCL_UNIX_FD
108# ifdef TCL_WIN_SOCKET
109# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
110# else
111# define TCL_UNIX_FD 1
112# endif
113#endif
114
Guido van Rossum00d93061998-05-28 23:06:38 +0000115/* Tcl_CreateFileHandler() changed several times; these macros deal with the
116 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
117 Unix, only because Jack added it back); when available on Windows, it only
118 applies to sockets. */
119
Guido van Rossum7bf15641998-05-22 18:28:17 +0000120#ifdef MS_WINDOWS
121#define FHANDLETYPE TCL_WIN_SOCKET
122#else
123#define FHANDLETYPE TCL_UNIX_FD
124#endif
125
Guido van Rossum00d93061998-05-28 23:06:38 +0000126/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
127 which uses this to handle Tcl events while the user is typing commands. */
128
129#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000130#define WAIT_FOR_STDIN
131#endif
132
Guido van Rossum00d93061998-05-28 23:06:38 +0000133#endif /* HAVE_CREATEFILEHANDLER */
134
Guido van Rossumad4db171998-06-13 13:56:28 +0000135#ifdef MS_WINDOWS
136#include <conio.h>
137#define WAIT_FOR_STDIN
138#endif
139
Guido van Rossum00d93061998-05-28 23:06:38 +0000140#ifdef WITH_THREAD
141
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000142/* The threading situation is complicated. Tcl is not thread-safe, except
143 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000144 So we need to use a lock around all uses of Tcl. Previously, the Python
145 interpreter lock was used for this. However, this causes problems when
146 other Python threads need to run while Tcl is blocked waiting for events.
147
148 To solve this problem, a separate lock for Tcl is introduced. Holding it
149 is incompatible with holding Python's interpreter lock. The following four
150 macros manipulate both locks together.
151
152 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
153 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
154 that could call an event handler, or otherwise affect the state of a Tcl
155 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000156 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000157 released and the lock for Tcl has been acquired.
158
Guido van Rossum5e977831998-06-15 14:03:52 +0000159 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
160 (For example, when transferring data from the Tcl interpreter result to a
161 Python string object.) This can be done by using different macros to close
162 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
163 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
164 releases the Tcl lock.
165
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000166 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000167 handlers when the handler needs to use Python. Such event handlers are
168 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000169 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000170 the Python interpreter lock, restoring the appropriate thread state, and
171 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
172 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000173 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000174
175 These locks expand to several statements and brackets; they should not be
176 used in branches of if statements and the like.
177
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000178 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
179 only valid in the thread that created it, and all Tk activity must happen in this
180 thread, also. That means that the mainloop must be invoked in the thread that
181 created the interpreter. Invoking commands from other threads is possible;
182 _tkinter will queue an event for the interpreter thread, which will then
183 execute the command and pass back the result. If the main thread is not in the
184 mainloop, and invoking commands causes an exception; if the main loop is running
185 but not processing events, the command invocation will block.
186
187 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
188 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
189 threads. So we use the Tcl TLS API.
190
Guido van Rossum00d93061998-05-28 23:06:38 +0000191*/
192
Guido van Rossum65d5b571998-12-21 19:32:43 +0000193static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000194
195#ifdef TCL_THREADS
196static Tcl_ThreadDataKey state_key;
197typedef PyThreadState *ThreadSpecificData;
198#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
199#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000200static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000201#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
203#define ENTER_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000204 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
205 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000206
207#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000208 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000209
Guido van Rossum62320c91998-06-15 04:36:09 +0000210#define ENTER_OVERLAP \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000211 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000212
213#define LEAVE_OVERLAP_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000214 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000215
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000216#define ENTER_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000217 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
218 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000219
220#define LEAVE_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000221 { PyThreadState *tstate = PyEval_SaveThread(); \
222 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000223
224#define CHECK_TCL_APPARTMENT \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000225 if (((TkappObject *)self)->threaded && \
226 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
227 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
228 return 0; \
229 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000230
231#else
232
233#define ENTER_TCL
234#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000235#define ENTER_OVERLAP
236#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000237#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000238#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000239#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000240
241#endif
242
Guido van Rossum97867b21996-08-08 19:09:53 +0000243#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000244#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000245#endif
246
Guido van Rossum18468821994-06-20 07:49:28 +0000247/**** Tkapp Object Declaration ****/
248
Jeremy Hylton938ace62002-07-17 16:30:39 +0000249static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000250
Guido van Rossum00d93061998-05-28 23:06:38 +0000251typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000252 PyObject_HEAD
253 Tcl_Interp *interp;
254 int wantobjects;
255 int threaded; /* True if tcl_platform[threaded] */
256 Tcl_ThreadId thread_id;
257 int dispatching;
258 /* We cannot include tclInt.h, as this is internal.
259 So we cache interesting types here. */
260 Tcl_ObjType *BooleanType;
261 Tcl_ObjType *ByteArrayType;
262 Tcl_ObjType *DoubleType;
263 Tcl_ObjType *IntType;
264 Tcl_ObjType *ListType;
265 Tcl_ObjType *ProcBodyType;
266 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000267} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000268
Christian Heimese93237d2007-12-19 02:37:44 +0000269#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000270#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000271#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000272
Guido van Rossum35d43371997-08-02 00:09:09 +0000273#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimese93237d2007-12-19 02:37:44 +0000274(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000275
Barry Warsawfa701a81997-01-16 00:15:11 +0000276
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000277
Guido van Rossum18468821994-06-20 07:49:28 +0000278/**** Error Handling ****/
279
280static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000281static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000282static int errorInCmd = 0;
283static PyObject *excInCmd;
284static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000285static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000286
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000287#ifdef TKINTER_PROTECT_LOADTK
288static int tk_load_failed;
289#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000290
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000291
Guido van Rossum18468821994-06-20 07:49:28 +0000292static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000293Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000294{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000295 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
296 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000297}
298
Barry Warsawfa701a81997-01-16 00:15:11 +0000299
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000300
Guido van Rossum18468821994-06-20 07:49:28 +0000301/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000302
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000303static int Tkinter_busywaitinterval = 20;
304
Guido van Rossum00d93061998-05-28 23:06:38 +0000305#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000306#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000307
Guido van Rossum00d93061998-05-28 23:06:38 +0000308/* Millisecond sleep() for Unix platforms. */
309
310static void
Fred Drake509d79a2000-07-08 04:04:38 +0000311Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000312{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000313 /* XXX Too bad if you don't have select(). */
314 struct timeval t;
315 t.tv_sec = milli/1000;
316 t.tv_usec = (milli%1000) * 1000;
317 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000318}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000319#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000320
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000321/* Wait up to 1s for the mainloop to come up. */
322
323static int
324WaitForMainloop(TkappObject* self)
325{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000326 int i;
327 for (i = 0; i < 10; i++) {
328 if (self->dispatching)
329 return 1;
330 Py_BEGIN_ALLOW_THREADS
331 Sleep(100);
332 Py_END_ALLOW_THREADS
333 }
334 if (self->dispatching)
335 return 1;
336 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
337 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000338}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000339#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000340
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000341
Guido van Rossum18468821994-06-20 07:49:28 +0000342static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000343AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000344{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000345 if (PyString_Check(value))
346 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000347#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000348 else if (PyUnicode_Check(value)) {
349 PyObject *v = PyUnicode_AsUTF8String(value);
350 if (v == NULL)
351 return NULL;
352 if (PyList_Append(tmp, v) != 0) {
353 Py_DECREF(v);
354 return NULL;
355 }
356 Py_DECREF(v);
357 return PyString_AsString(v);
358 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000359#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000360 else {
361 PyObject *v = PyObject_Str(value);
362 if (v == NULL)
363 return NULL;
364 if (PyList_Append(tmp, v) != 0) {
365 Py_DECREF(v);
366 return NULL;
367 }
368 Py_DECREF(v);
369 return PyString_AsString(v);
370 }
Guido van Rossum18468821994-06-20 07:49:28 +0000371}
372
Barry Warsawfa701a81997-01-16 00:15:11 +0000373
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000374
Guido van Rossum18468821994-06-20 07:49:28 +0000375#define ARGSZ 64
376
377static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000378Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000379{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000380 PyObject *tmp = NULL;
381 char *argvStore[ARGSZ];
382 char **argv = NULL;
383 int fvStore[ARGSZ];
384 int *fv = NULL;
Serhiy Storchaka42035702013-08-21 21:46:12 +0300385 Py_ssize_t argc = 0, fvc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000386 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000387
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000388 if (!(tmp = PyList_New(0)))
389 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000390
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000391 argv = argvStore;
392 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000393
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000394 if (args == NULL)
395 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000396
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000397 else if (!PyTuple_Check(args)) {
398 argc = 1;
399 fv[0] = 0;
400 if (!(argv[0] = AsString(args, tmp)))
401 goto finally;
402 }
403 else {
404 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000405
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000406 if (argc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +0300407 if (!CHECK_SIZE(argc, sizeof(char *))) {
408 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
409 goto finally;
410 }
411 argv = (char **)ckalloc((size_t)argc * sizeof(char *));
412 fv = (int *)ckalloc((size_t)argc * sizeof(int));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000413 if (argv == NULL || fv == NULL) {
414 PyErr_NoMemory();
415 goto finally;
416 }
417 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000418
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000419 for (i = 0; i < argc; i++) {
420 PyObject *v = PyTuple_GetItem(args, i);
421 if (PyTuple_Check(v)) {
422 fv[i] = 1;
423 if (!(argv[i] = Merge(v)))
424 goto finally;
425 fvc++;
426 }
427 else if (v == Py_None) {
428 argc = i;
429 break;
430 }
431 else {
432 fv[i] = 0;
433 if (!(argv[i] = AsString(v, tmp)))
434 goto finally;
435 fvc++;
436 }
437 }
438 }
439 res = Tcl_Merge(argc, argv);
440 if (res == NULL)
441 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000442
Barry Warsawfa701a81997-01-16 00:15:11 +0000443 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000444 for (i = 0; i < fvc; i++)
445 if (fv[i]) {
446 ckfree(argv[i]);
447 }
448 if (argv != argvStore)
449 ckfree(FREECAST argv);
450 if (fv != fvStore)
451 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000452
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000453 Py_DECREF(tmp);
454 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000455}
456
Barry Warsawfa701a81997-01-16 00:15:11 +0000457
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000458
Guido van Rossum18468821994-06-20 07:49:28 +0000459static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000460Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000461{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000462 int argc;
463 char **argv;
464 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000465
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000466 if (list == NULL) {
467 Py_INCREF(Py_None);
468 return Py_None;
469 }
Guido van Rossum18468821994-06-20 07:49:28 +0000470
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000471 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
472 /* Not a list.
473 * Could be a quoted string containing funnies, e.g. {"}.
474 * Return the string itself.
475 */
476 return PyString_FromString(list);
477 }
Guido van Rossum18468821994-06-20 07:49:28 +0000478
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000479 if (argc == 0)
480 v = PyString_FromString("");
481 else if (argc == 1)
482 v = PyString_FromString(argv[0]);
483 else if ((v = PyTuple_New(argc)) != NULL) {
484 int i;
485 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000486
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000487 for (i = 0; i < argc; i++) {
488 if ((w = Split(argv[i])) == NULL) {
489 Py_DECREF(v);
490 v = NULL;
491 break;
492 }
493 PyTuple_SetItem(v, i, w);
494 }
495 }
496 Tcl_Free(FREECAST argv);
497 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000498}
499
Martin v. Löwisffad6332002-11-26 09:28:05 +0000500/* In some cases, Tcl will still return strings that are supposed to be
501 lists. SplitObj walks through a nested tuple, finding string objects that
502 need to be split. */
503
Martin v. Löwis111c1802008-06-13 07:47:47 +0000504static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000505SplitObj(PyObject *arg)
506{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000507 if (PyTuple_Check(arg)) {
508 int i, size;
509 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000510
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000511 size = PyTuple_Size(arg);
512 result = NULL;
513 /* Recursively invoke SplitObj for all tuple items.
514 If this does not return a new object, no action is
515 needed. */
516 for(i = 0; i < size; i++) {
517 elem = PyTuple_GetItem(arg, i);
518 newelem = SplitObj(elem);
519 if (!newelem) {
520 Py_XDECREF(result);
521 return NULL;
522 }
523 if (!result) {
524 int k;
525 if (newelem == elem) {
526 Py_DECREF(newelem);
527 continue;
528 }
529 result = PyTuple_New(size);
530 if (!result)
531 return NULL;
532 for(k = 0; k < i; k++) {
533 elem = PyTuple_GetItem(arg, k);
534 Py_INCREF(elem);
535 PyTuple_SetItem(result, k, elem);
536 }
537 }
538 PyTuple_SetItem(result, i, newelem);
539 }
540 if (result)
541 return result;
542 /* Fall through, returning arg. */
543 }
544 else if (PyString_Check(arg)) {
545 int argc;
546 char **argv;
547 char *list = PyString_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000548
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000549 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
550 Py_INCREF(arg);
551 return arg;
552 }
553 Tcl_Free(FREECAST argv);
554 if (argc > 1)
555 return Split(PyString_AsString(arg));
556 /* Fall through, returning arg. */
557 }
Serhiy Storchakafab65422013-07-11 20:32:48 +0300558 else if (PyUnicode_Check(arg)) {
559 int argc;
560 char **argv;
561 char *list;
562 PyObject *s = PyUnicode_AsUTF8String(arg);
563
564 if (s == NULL) {
565 Py_INCREF(arg);
566 return arg;
567 }
568 list = PyString_AsString(s);
569
570 if (list == NULL ||
571 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
572 Py_DECREF(s);
573 Py_INCREF(arg);
574 return arg;
575 }
576 Tcl_Free(FREECAST argv);
577 if (argc > 1) {
578 PyObject *v = Split(list);
579 Py_DECREF(s);
580 return v;
581 }
582 Py_DECREF(s);
583 /* Fall through, returning arg. */
584 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000585 Py_INCREF(arg);
586 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000587}
Barry Warsawfa701a81997-01-16 00:15:11 +0000588
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000589
Guido van Rossum18468821994-06-20 07:49:28 +0000590/**** Tkapp Object ****/
591
592#ifndef WITH_APPINIT
593int
Fred Drake509d79a2000-07-08 04:04:38 +0000594Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000595{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000596 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000597
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000598 if (Tcl_Init(interp) == TCL_ERROR) {
599 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
600 return TCL_ERROR;
601 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000602
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000603 _tkinter_skip_tk_init = Tcl_GetVar(interp,
604 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
605 if (_tkinter_skip_tk_init != NULL &&
606 strcmp(_tkinter_skip_tk_init, "1") == 0) {
607 return TCL_OK;
608 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000609
610#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000611 if (tk_load_failed) {
612 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
613 return TCL_ERROR;
614 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000615#endif
616
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000617 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000618#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000619 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000620#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000621 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
622 return TCL_ERROR;
623 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000624
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000625 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000626}
627#endif /* !WITH_APPINIT */
628
Guido van Rossum18468821994-06-20 07:49:28 +0000629
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000630
Barry Warsawfa701a81997-01-16 00:15:11 +0000631
632/* Initialize the Tk application; see the `main' function in
633 * `tkMain.c'.
634 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000635
Thomas Wouters58d05102000-07-24 14:43:35 +0000636static void EnableEventHook(void); /* Forward */
637static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000638
Barry Warsawfa701a81997-01-16 00:15:11 +0000639static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000640Tkapp_New(char *screenName, char *baseName, char *className,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000641 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000642{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000643 TkappObject *v;
644 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000645
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000646 v = PyObject_New(TkappObject, &Tkapp_Type);
647 if (v == NULL)
648 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000649
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000650 v->interp = Tcl_CreateInterp();
651 v->wantobjects = wantobjects;
652 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
653 TCL_GLOBAL_ONLY) != NULL;
654 v->thread_id = Tcl_GetCurrentThread();
655 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000656
657#ifndef TCL_THREADS
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000658 if (v->threaded) {
659 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
660 Py_DECREF(v);
661 return 0;
662 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000663#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000664#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000665 if (v->threaded && tcl_lock) {
666 /* If Tcl is threaded, we don't need the lock. */
667 PyThread_free_lock(tcl_lock);
668 tcl_lock = NULL;
669 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000670#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000671
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000672 v->BooleanType = Tcl_GetObjType("boolean");
673 v->ByteArrayType = Tcl_GetObjType("bytearray");
674 v->DoubleType = Tcl_GetObjType("double");
675 v->IntType = Tcl_GetObjType("int");
676 v->ListType = Tcl_GetObjType("list");
677 v->ProcBodyType = Tcl_GetObjType("procbody");
678 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000679
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000680 /* Delete the 'exit' command, which can screw things up */
681 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000682
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000683 if (screenName != NULL)
684 Tcl_SetVar2(v->interp, "env", "DISPLAY",
685 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000686
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000687 if (interactive)
688 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
689 else
690 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000691
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000692 /* This is used to get the application class for Tk 4.1 and up */
693 argv0 = (char*)ckalloc(strlen(className) + 1);
694 if (!argv0) {
695 PyErr_NoMemory();
696 Py_DECREF(v);
697 return NULL;
698 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000699
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000700 strcpy(argv0, className);
Antoine Pitrou44b3b542011-10-04 13:55:37 +0200701 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
702 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000703 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
704 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000705
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000706 if (! wantTk) {
707 Tcl_SetVar(v->interp,
708 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
709 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000710#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000711 else if (tk_load_failed) {
712 Tcl_SetVar(v->interp,
713 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
714 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000715#endif
David Aschere2b4b322004-02-18 05:59:53 +0000716
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000717 /* some initial arguments need to be in argv */
718 if (sync || use) {
719 char *args;
720 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000721
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000722 if (sync)
723 len += sizeof "-sync";
724 if (use)
725 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000726
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000727 args = (char*)ckalloc(len);
728 if (!args) {
729 PyErr_NoMemory();
730 Py_DECREF(v);
731 return NULL;
732 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000733
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000734 args[0] = '\0';
735 if (sync)
736 strcat(args, "-sync");
737 if (use) {
738 if (sync)
739 strcat(args, " ");
740 strcat(args, "-use ");
741 strcat(args, use);
742 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000743
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000744 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
745 ckfree(args);
746 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000747
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000748 if (Tcl_AppInit(v->interp) != TCL_OK) {
749 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000750#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000751 if (wantTk) {
752 const char *_tkinter_tk_failed;
753 _tkinter_tk_failed = Tcl_GetVar(v->interp,
754 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000755
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000756 if ( _tkinter_tk_failed != NULL &&
757 strcmp(_tkinter_tk_failed, "1") == 0) {
758 tk_load_failed = 1;
759 }
760 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000761#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000762 Py_DECREF((PyObject *)v);
763 return (TkappObject *)result;
764 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000765
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000766 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000767
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000768 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000769}
770
Barry Warsawfa701a81997-01-16 00:15:11 +0000771
Guilherme Polo1972d162009-03-27 21:43:08 +0000772#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000773static void
774Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000775 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000776{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000777 Py_BEGIN_ALLOW_THREADS;
778 Tcl_MutexLock(mutex);
779 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
780 Tcl_ThreadAlert(self->thread_id);
781 Tcl_ConditionWait(cond, mutex, NULL);
782 Tcl_MutexUnlock(mutex);
783 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000784}
Guilherme Polo1972d162009-03-27 21:43:08 +0000785#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000786
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000787
Guido van Rossum18468821994-06-20 07:49:28 +0000788/** Tcl Eval **/
789
Martin v. Löwisffad6332002-11-26 09:28:05 +0000790typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000791 PyObject_HEAD
792 Tcl_Obj *value;
793 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000794} PyTclObject;
795
796staticforward PyTypeObject PyTclObject_Type;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000797#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000798
799static PyObject *
800newPyTclObject(Tcl_Obj *arg)
801{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000802 PyTclObject *self;
803 self = PyObject_New(PyTclObject, &PyTclObject_Type);
804 if (self == NULL)
805 return NULL;
806 Tcl_IncrRefCount(arg);
807 self->value = arg;
808 self->string = NULL;
809 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000810}
811
812static void
813PyTclObject_dealloc(PyTclObject *self)
814{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000815 Tcl_DecrRefCount(self->value);
816 Py_XDECREF(self->string);
817 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000818}
819
820static PyObject *
821PyTclObject_str(PyTclObject *self)
822{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000823 if (self->string && PyString_Check(self->string)) {
824 Py_INCREF(self->string);
825 return self->string;
826 }
827 /* XXX Could cache value if it is an ASCII string. */
828 return PyString_FromString(Tcl_GetString(self->value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000829}
830
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000831static char*
832PyTclObject_TclString(PyObject *self)
833{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000834 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000835}
836
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000837/* Like _str, but create Unicode if necessary. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000838PyDoc_STRVAR(PyTclObject_string__doc__,
Martin v. Löwis39195712003-01-04 00:33:13 +0000839"the string representation of this object, either as string or Unicode");
840
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000841static PyObject *
842PyTclObject_string(PyTclObject *self, void *ignored)
843{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000844 char *s;
845 int i, len;
846 if (!self->string) {
847 s = Tcl_GetStringFromObj(self->value, &len);
848 for (i = 0; i < len; i++)
849 if (s[i] & 0x80)
850 break;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000851#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000852 if (i == len)
853 /* It is an ASCII string. */
854 self->string = PyString_FromStringAndSize(s, len);
855 else {
856 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
857 if (!self->string) {
858 PyErr_Clear();
859 self->string = PyString_FromStringAndSize(s, len);
860 }
861 }
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000862#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000863 self->string = PyString_FromStringAndSize(s, len);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000864#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000865 if (!self->string)
866 return NULL;
867 }
868 Py_INCREF(self->string);
869 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000870}
871
872#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000873PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
874
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000875static PyObject *
876PyTclObject_unicode(PyTclObject *self, void *ignored)
877{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000878 char *s;
879 int len;
880 if (self->string && PyUnicode_Check(self->string)) {
881 Py_INCREF(self->string);
882 return self->string;
883 }
884 /* XXX Could chache result if it is non-ASCII. */
885 s = Tcl_GetStringFromObj(self->value, &len);
886 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000887}
888#endif
889
Martin v. Löwisffad6332002-11-26 09:28:05 +0000890static PyObject *
891PyTclObject_repr(PyTclObject *self)
892{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000893 char buf[50];
894 PyOS_snprintf(buf, 50, "<%s object at %p>",
895 self->value->typePtr->name, self->value);
896 return PyString_FromString(buf);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000897}
898
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000899static int
900PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
901{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000902 int res;
903 res = strcmp(Tcl_GetString(self->value),
904 Tcl_GetString(other->value));
905 if (res < 0) return -1;
906 if (res > 0) return 1;
907 return 0;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000908}
909
Martin v. Löwis39195712003-01-04 00:33:13 +0000910PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
911
Martin v. Löwisffad6332002-11-26 09:28:05 +0000912static PyObject*
913get_typename(PyTclObject* obj, void* ignored)
914{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000915 return PyString_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000916}
917
Martin v. Löwis39195712003-01-04 00:33:13 +0000918
Martin v. Löwisffad6332002-11-26 09:28:05 +0000919static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000920 {"typename", (getter)get_typename, NULL, get_typename__doc__},
921 {"string", (getter)PyTclObject_string, NULL,
922 PyTclObject_string__doc__},
923 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000924};
925
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000926static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000927#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000928 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
929 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000930#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000931 {0}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000932};
933
Martin v. Löwisffad6332002-11-26 09:28:05 +0000934statichere PyTypeObject PyTclObject_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000935 PyObject_HEAD_INIT(NULL)
936 0, /*ob_size*/
937 "_tkinter.Tcl_Obj", /*tp_name*/
938 sizeof(PyTclObject), /*tp_basicsize*/
939 0, /*tp_itemsize*/
940 /* methods */
941 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
942 0, /*tp_print*/
943 0, /*tp_getattr*/
944 0, /*tp_setattr*/
945 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
946 (reprfunc)PyTclObject_repr, /*tp_repr*/
947 0, /*tp_as_number*/
948 0, /*tp_as_sequence*/
949 0, /*tp_as_mapping*/
950 0, /*tp_hash*/
951 0, /*tp_call*/
952 (reprfunc)PyTclObject_str, /*tp_str*/
953 PyObject_GenericGetAttr,/*tp_getattro*/
954 0, /*tp_setattro*/
955 0, /*tp_as_buffer*/
956 Py_TPFLAGS_DEFAULT, /*tp_flags*/
957 0, /*tp_doc*/
958 0, /*tp_traverse*/
959 0, /*tp_clear*/
960 0, /*tp_richcompare*/
961 0, /*tp_weaklistoffset*/
962 0, /*tp_iter*/
963 0, /*tp_iternext*/
964 PyTclObject_methods, /*tp_methods*/
965 0, /*tp_members*/
966 PyTclObject_getsetlist, /*tp_getset*/
967 0, /*tp_base*/
968 0, /*tp_dict*/
969 0, /*tp_descr_get*/
970 0, /*tp_descr_set*/
971 0, /*tp_dictoffset*/
972 0, /*tp_init*/
973 0, /*tp_alloc*/
974 0, /*tp_new*/
975 0, /*tp_free*/
976 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000977};
978
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000979static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000980AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000981{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000982 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000983
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000984 if (PyString_Check(value))
985 return Tcl_NewStringObj(PyString_AS_STRING(value),
986 PyString_GET_SIZE(value));
987 else if (PyBool_Check(value))
988 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
989 else if (PyInt_Check(value))
990 return Tcl_NewLongObj(PyInt_AS_LONG(value));
991 else if (PyFloat_Check(value))
992 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
993 else if (PyTuple_Check(value)) {
Serhiy Storchaka42035702013-08-21 21:46:12 +0300994 Tcl_Obj **argv;
995 Py_ssize_t size, i;
996
997 size = PyTuple_Size(value);
998 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
999 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1000 return NULL;
1001 }
1002 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001003 if(!argv)
1004 return 0;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001005 for (i = 0; i < size; i++)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001006 argv[i] = AsObj(PyTuple_GetItem(value,i));
1007 result = Tcl_NewListObj(PyTuple_Size(value), argv);
1008 ckfree(FREECAST argv);
1009 return result;
1010 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001011#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001012 else if (PyUnicode_Check(value)) {
1013 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
1014 Py_ssize_t size = PyUnicode_GET_SIZE(value);
1015 /* This #ifdef assumes that Tcl uses UCS-2.
1016 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001017#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001018 Tcl_UniChar *outbuf = NULL;
1019 Py_ssize_t i;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001020 size_t allocsize;
1021 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1022 PyErr_SetString(PyExc_OverflowError, "string is too long");
1023 return NULL;
1024 }
1025 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001026 if (allocsize >= size)
1027 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
1028 /* Else overflow occurred, and we take the next exit */
1029 if (!outbuf) {
1030 PyErr_NoMemory();
1031 return NULL;
1032 }
1033 for (i = 0; i < size; i++) {
1034 if (inbuf[i] >= 0x10000) {
1035 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka46764482013-02-18 13:00:08 +02001036 PyErr_Format(Tkinter_TclError,
1037 "character U+%x is above the range "
1038 "(U+0000-U+FFFF) allowed by Tcl",
1039 (int)inbuf[i]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001040 ckfree(FREECAST outbuf);
1041 return NULL;
1042 }
1043 outbuf[i] = inbuf[i];
1044 }
1045 result = Tcl_NewUnicodeObj(outbuf, size);
1046 ckfree(FREECAST outbuf);
1047 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001048#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001049 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001050#endif
1051
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001052 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001053#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001054 else if(PyTclObject_Check(value)) {
1055 Tcl_Obj *v = ((PyTclObject*)value)->value;
1056 Tcl_IncrRefCount(v);
1057 return v;
1058 }
1059 else {
1060 PyObject *v = PyObject_Str(value);
1061 if (!v)
1062 return 0;
1063 result = AsObj(v);
1064 Py_DECREF(v);
1065 return result;
1066 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001067}
1068
Martin v. Löwisffad6332002-11-26 09:28:05 +00001069static PyObject*
1070FromObj(PyObject* tkapp, Tcl_Obj *value)
1071{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001072 PyObject *result = NULL;
1073 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001074
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001075 if (value->typePtr == NULL) {
1076 /* If the result contains any bytes with the top bit set,
1077 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001078#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001079 int i;
1080 char *s = value->bytes;
1081 int len = value->length;
1082 for (i = 0; i < len; i++) {
1083 if (value->bytes[i] & 0x80)
1084 break;
1085 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001086
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001087 if (i == value->length)
1088 result = PyString_FromStringAndSize(s, len);
1089 else {
1090 /* Convert UTF-8 to Unicode string */
1091 result = PyUnicode_DecodeUTF8(s, len, "strict");
1092 if (result == NULL) {
1093 PyErr_Clear();
1094 result = PyString_FromStringAndSize(s, len);
1095 }
1096 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001097#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001098 result = PyString_FromStringAndSize(value->bytes, value->length);
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001099#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001100 return result;
1101 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001102
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001103 if (value->typePtr == app->BooleanType) {
1104 result = value->internalRep.longValue ? Py_True : Py_False;
1105 Py_INCREF(result);
1106 return result;
1107 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001108
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001109 if (value->typePtr == app->ByteArrayType) {
1110 int size;
1111 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1112 return PyString_FromStringAndSize(data, size);
1113 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001114
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001115 if (value->typePtr == app->DoubleType) {
1116 return PyFloat_FromDouble(value->internalRep.doubleValue);
1117 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001118
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001119 if (value->typePtr == app->IntType) {
1120 return PyInt_FromLong(value->internalRep.longValue);
1121 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001122
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001123 if (value->typePtr == app->ListType) {
1124 int size;
1125 int i, status;
1126 PyObject *elem;
1127 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001128
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001129 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1130 if (status == TCL_ERROR)
1131 return Tkinter_Error(tkapp);
1132 result = PyTuple_New(size);
1133 if (!result)
1134 return NULL;
1135 for (i = 0; i < size; i++) {
1136 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1137 value, i, &tcl_elem);
1138 if (status == TCL_ERROR) {
1139 Py_DECREF(result);
1140 return Tkinter_Error(tkapp);
1141 }
1142 elem = FromObj(tkapp, tcl_elem);
1143 if (!elem) {
1144 Py_DECREF(result);
1145 return NULL;
1146 }
1147 PyTuple_SetItem(result, i, elem);
1148 }
1149 return result;
1150 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001151
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001152 if (value->typePtr == app->ProcBodyType) {
1153 /* fall through: return tcl object. */
1154 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001155
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001156 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001157#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001158#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001159 PyObject *result;
1160 int size;
1161 Tcl_UniChar *input;
1162 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001163
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001164 size = Tcl_GetCharLength(value);
1165 result = PyUnicode_FromUnicode(NULL, size);
1166 if (!result)
1167 return NULL;
1168 input = Tcl_GetUnicode(value);
1169 output = PyUnicode_AS_UNICODE(result);
1170 while (size--)
1171 *output++ = *input++;
1172 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001173#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001174 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1175 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001176#endif
1177#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001178 int size;
1179 char *c;
1180 c = Tcl_GetStringFromObj(value, &size);
1181 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001182#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001183 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001184
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001185 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001186}
1187
Guilherme Polo1972d162009-03-27 21:43:08 +00001188#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001189/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001190TCL_DECLARE_MUTEX(call_mutex)
1191
1192typedef struct Tkapp_CallEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001193 Tcl_Event ev; /* Must be first */
1194 TkappObject *self;
1195 PyObject *args;
1196 int flags;
1197 PyObject **res;
1198 PyObject **exc_type, **exc_value, **exc_tb;
1199 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001200} Tkapp_CallEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001201#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001202
1203void
1204Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001205{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001206 int i;
1207 for (i = 0; i < objc; i++)
1208 Tcl_DecrRefCount(objv[i]);
1209 if (objv != objStore)
1210 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001211}
Guido van Rossum18468821994-06-20 07:49:28 +00001212
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001213/* Convert Python objects to Tcl objects. This must happen in the
1214 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001215
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001216static Tcl_Obj**
1217Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1218{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001219 Tcl_Obj **objv = objStore;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001220 Py_ssize_t objc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001221 if (args == NULL)
1222 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001223
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001224 else if (!PyTuple_Check(args)) {
1225 objv[0] = AsObj(args);
1226 if (objv[0] == 0)
1227 goto finally;
1228 objc = 1;
1229 Tcl_IncrRefCount(objv[0]);
1230 }
1231 else {
1232 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001233
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001234 if (objc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001235 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1236 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1237 return NULL;
1238 }
1239 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001240 if (objv == NULL) {
1241 PyErr_NoMemory();
1242 objc = 0;
1243 goto finally;
1244 }
1245 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001246
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001247 for (i = 0; i < objc; i++) {
1248 PyObject *v = PyTuple_GetItem(args, i);
1249 if (v == Py_None) {
1250 objc = i;
1251 break;
1252 }
1253 objv[i] = AsObj(v);
1254 if (!objv[i]) {
1255 /* Reset objc, so it attempts to clear
1256 objects only up to i. */
1257 objc = i;
1258 goto finally;
1259 }
1260 Tcl_IncrRefCount(objv[i]);
1261 }
1262 }
1263 *pobjc = objc;
1264 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001265finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001266 Tkapp_CallDeallocArgs(objv, objStore, objc);
1267 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001268}
Guido van Rossum212643f1998-04-29 16:22:14 +00001269
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001270/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001271
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001272static PyObject*
1273Tkapp_CallResult(TkappObject *self)
1274{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001275 PyObject *res = NULL;
1276 if(self->wantobjects) {
1277 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1278 /* Not sure whether the IncrRef is necessary, but something
1279 may overwrite the interpreter result while we are
1280 converting it. */
1281 Tcl_IncrRefCount(value);
1282 res = FromObj((PyObject*)self, value);
1283 Tcl_DecrRefCount(value);
1284 } else {
1285 const char *s = Tcl_GetStringResult(self->interp);
1286 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001287
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001288 /* If the result contains any bytes with the top bit set,
1289 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001290#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001291 while (*p != '\0') {
1292 if (*p & 0x80)
1293 break;
1294 p++;
1295 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001296
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001297 if (*p == '\0')
1298 res = PyString_FromStringAndSize(s, (int)(p-s));
1299 else {
1300 /* Convert UTF-8 to Unicode string */
1301 p = strchr(p, '\0');
1302 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1303 if (res == NULL) {
1304 PyErr_Clear();
1305 res = PyString_FromStringAndSize(s, (int)(p-s));
1306 }
1307 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001308#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001309 p = strchr(p, '\0');
1310 res = PyString_FromStringAndSize(s, (int)(p-s));
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001311#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001312 }
1313 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001314}
Guido van Rossum632de272000-03-29 00:19:50 +00001315
Guilherme Polo1972d162009-03-27 21:43:08 +00001316#ifdef WITH_THREAD
1317
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001318/* Tkapp_CallProc is the event procedure that is executed in the context of
1319 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1320 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001321
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001322static int
1323Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1324{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001325 Tcl_Obj *objStore[ARGSZ];
1326 Tcl_Obj **objv;
1327 int objc;
1328 int i;
1329 ENTER_PYTHON
1330 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1331 if (!objv) {
1332 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1333 *(e->res) = NULL;
1334 }
1335 LEAVE_PYTHON
1336 if (!objv)
1337 goto done;
1338 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1339 ENTER_PYTHON
1340 if (i == TCL_ERROR) {
1341 *(e->res) = NULL;
1342 *(e->exc_type) = NULL;
1343 *(e->exc_tb) = NULL;
1344 *(e->exc_value) = PyObject_CallFunction(
1345 Tkinter_TclError, "s",
1346 Tcl_GetStringResult(e->self->interp));
1347 }
1348 else {
1349 *(e->res) = Tkapp_CallResult(e->self);
1350 }
1351 LEAVE_PYTHON
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001352
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001353 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001354done:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001355 /* Wake up calling thread. */
1356 Tcl_MutexLock(&call_mutex);
1357 Tcl_ConditionNotify(e->done);
1358 Tcl_MutexUnlock(&call_mutex);
1359 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001360}
1361
Guilherme Polo1972d162009-03-27 21:43:08 +00001362#endif
1363
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001364/* This is the main entry point for calling a Tcl command.
1365 It supports three cases, with regard to threading:
1366 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1367 the context of the calling thread.
1368 2. Tcl is threaded, caller of the command is in the interpreter thread:
1369 Execute the command in the calling thread. Since the Tcl lock will
1370 not be used, we can merge that with case 1.
1371 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1372 the interpreter thread. Allocation of Tcl objects needs to occur in the
1373 interpreter thread, so we ship the PyObject* args to the target thread,
1374 and perform processing there. */
1375
1376static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001377Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001378{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001379 Tcl_Obj *objStore[ARGSZ];
1380 Tcl_Obj **objv = NULL;
1381 int objc, i;
1382 PyObject *res = NULL;
1383 TkappObject *self = (TkappObject*)selfptr;
1384 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001385
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001386 /* If args is a single tuple, replace with contents of tuple */
1387 if (1 == PyTuple_Size(args)){
1388 PyObject* item = PyTuple_GetItem(args, 0);
1389 if (PyTuple_Check(item))
1390 args = item;
1391 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001392#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001393 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1394 /* We cannot call the command directly. Instead, we must
1395 marshal the parameters to the interpreter thread. */
1396 Tkapp_CallEvent *ev;
1397 Tcl_Condition cond = NULL;
1398 PyObject *exc_type, *exc_value, *exc_tb;
1399 if (!WaitForMainloop(self))
1400 return NULL;
1401 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1402 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1403 ev->self = self;
1404 ev->args = args;
1405 ev->res = &res;
1406 ev->exc_type = &exc_type;
1407 ev->exc_value = &exc_value;
1408 ev->exc_tb = &exc_tb;
1409 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001410
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001411 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001412
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001413 if (res == NULL) {
1414 if (exc_type)
1415 PyErr_Restore(exc_type, exc_value, exc_tb);
1416 else
1417 PyErr_SetObject(Tkinter_TclError, exc_value);
1418 }
1419 Tcl_ConditionFinalize(&cond);
1420 }
1421 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001422#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001423 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001424
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001425 objv = Tkapp_CallArgs(args, objStore, &objc);
1426 if (!objv)
1427 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001428
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001429 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001430
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001431 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001432
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001433 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001434
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001435 if (i == TCL_ERROR)
1436 Tkinter_Error(selfptr);
1437 else
1438 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001439
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001440 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001441
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001442 Tkapp_CallDeallocArgs(objv, objStore, objc);
1443 }
1444 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001445}
1446
1447
1448static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001449Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001450{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001451 /* Could do the same here as for Tkapp_Call(), but this is not used
1452 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1453 way for the user to do what all its Global* variants do (save and
1454 reset the scope pointer, call the local version, restore the saved
1455 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001456
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001457 char *cmd;
1458 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001459
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001460 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001461
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001462 cmd = Merge(args);
1463 if (cmd) {
1464 int err;
1465 ENTER_TCL
1466 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1467 ENTER_OVERLAP
1468 if (err == TCL_ERROR)
1469 res = Tkinter_Error(self);
1470 else
1471 res = PyString_FromString(Tkapp_Result(self));
1472 LEAVE_OVERLAP_TCL
1473 ckfree(cmd);
1474 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001475
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001476 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001477}
1478
1479static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001480Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001481{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001482 char *script;
1483 PyObject *res = NULL;
1484 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001485
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001486 if (!PyArg_ParseTuple(args, "s:eval", &script))
1487 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001488
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001489 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001490
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001491 ENTER_TCL
1492 err = Tcl_Eval(Tkapp_Interp(self), script);
1493 ENTER_OVERLAP
1494 if (err == TCL_ERROR)
1495 res = Tkinter_Error(self);
1496 else
1497 res = PyString_FromString(Tkapp_Result(self));
1498 LEAVE_OVERLAP_TCL
1499 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001500}
1501
1502static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001503Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001504{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001505 char *script;
1506 PyObject *res = NULL;
1507 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001508
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001509 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1510 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001511
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001512 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001513
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001514 ENTER_TCL
1515 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1516 ENTER_OVERLAP
1517 if (err == TCL_ERROR)
1518 res = Tkinter_Error(self);
1519 else
1520 res = PyString_FromString(Tkapp_Result(self));
1521 LEAVE_OVERLAP_TCL
1522 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001523}
1524
1525static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001526Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001527{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001528 char *fileName;
1529 PyObject *res = NULL;
1530 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001531
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001532 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1533 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001534
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001535 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001537 ENTER_TCL
1538 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1539 ENTER_OVERLAP
1540 if (err == TCL_ERROR)
1541 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001542
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001543 else
1544 res = PyString_FromString(Tkapp_Result(self));
1545 LEAVE_OVERLAP_TCL
1546 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001547}
1548
1549static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001550Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001551{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001552 char *script;
1553 PyObject *res = NULL;
1554 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001555
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001556 if (!PyArg_ParseTuple(args, "s", &script))
1557 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001558
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001559 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001560
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001561 ENTER_TCL
1562 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1563 ENTER_OVERLAP
1564 if (err == TCL_ERROR)
1565 res = Tkinter_Error(self);
1566 else
1567 res = PyString_FromString(Tkapp_Result(self));
1568 LEAVE_OVERLAP_TCL
1569 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001570}
1571
1572static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001573Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001574{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001575 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001576
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001577 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1578 return NULL;
1579 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001580
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001581 ENTER_TCL
1582 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1583 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001584
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001585 Py_INCREF(Py_None);
1586 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001587}
1588
Barry Warsawfa701a81997-01-16 00:15:11 +00001589
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001590
Guido van Rossum18468821994-06-20 07:49:28 +00001591/** Tcl Variable **/
1592
Guilherme Polo1972d162009-03-27 21:43:08 +00001593typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1594
1595#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001596TCL_DECLARE_MUTEX(var_mutex)
1597
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001598typedef struct VarEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001599 Tcl_Event ev; /* must be first */
1600 PyObject *self;
1601 PyObject *args;
1602 int flags;
1603 EventFunc func;
1604 PyObject **res;
1605 PyObject **exc_type;
1606 PyObject **exc_val;
1607 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001608} VarEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001609#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001610
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001611static int
1612varname_converter(PyObject *in, void *_out)
1613{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001614 char **out = (char**)_out;
1615 if (PyString_Check(in)) {
1616 *out = PyString_AsString(in);
1617 return 1;
1618 }
1619 if (PyTclObject_Check(in)) {
1620 *out = PyTclObject_TclString(in);
1621 return 1;
1622 }
1623 /* XXX: Should give diagnostics. */
1624 return 0;
1625}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001626
Guilherme Polo1972d162009-03-27 21:43:08 +00001627#ifdef WITH_THREAD
1628
Martin v. Löwis111c1802008-06-13 07:47:47 +00001629static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001630var_perform(VarEvent *ev)
1631{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001632 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1633 if (!*(ev->res)) {
1634 PyObject *exc, *val, *tb;
1635 PyErr_Fetch(&exc, &val, &tb);
1636 PyErr_NormalizeException(&exc, &val, &tb);
1637 *(ev->exc_type) = exc;
1638 *(ev->exc_val) = val;
1639 Py_DECREF(tb);
1640 }
1641
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001642}
1643
1644static int
1645var_proc(VarEvent* ev, int flags)
1646{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001647 ENTER_PYTHON
1648 var_perform(ev);
1649 Tcl_MutexLock(&var_mutex);
1650 Tcl_ConditionNotify(ev->cond);
1651 Tcl_MutexUnlock(&var_mutex);
1652 LEAVE_PYTHON
1653 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001654}
1655
Guilherme Polo1972d162009-03-27 21:43:08 +00001656#endif
1657
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001658static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001659var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001660{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001661#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001662 TkappObject *self = (TkappObject*)selfptr;
1663 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1664 TkappObject *self = (TkappObject*)selfptr;
1665 VarEvent *ev;
1666 PyObject *res, *exc_type, *exc_val;
1667 Tcl_Condition cond = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001668
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001669 /* The current thread is not the interpreter thread. Marshal
1670 the call to the interpreter thread, then wait for
1671 completion. */
1672 if (!WaitForMainloop(self))
1673 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001674
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001675 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1676
1677 ev->self = selfptr;
1678 ev->args = args;
1679 ev->flags = flags;
1680 ev->func = func;
1681 ev->res = &res;
1682 ev->exc_type = &exc_type;
1683 ev->exc_val = &exc_val;
1684 ev->cond = &cond;
1685 ev->ev.proc = (Tcl_EventProc*)var_proc;
1686 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1687 Tcl_ConditionFinalize(&cond);
1688 if (!res) {
1689 PyErr_SetObject(exc_type, exc_val);
1690 Py_DECREF(exc_type);
1691 Py_DECREF(exc_val);
1692 return NULL;
1693 }
1694 return res;
1695 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001696#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001697 /* Tcl is not threaded, or this is the interpreter thread. */
1698 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001699}
1700
Guido van Rossum18468821994-06-20 07:49:28 +00001701static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001702SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001703{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001704 char *name1, *name2;
1705 PyObject *newValue;
1706 PyObject *res = NULL;
1707 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001708
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001709 if (PyArg_ParseTuple(args, "O&O:setvar",
1710 varname_converter, &name1, &newValue)) {
1711 /* XXX Acquire tcl lock??? */
1712 newval = AsObj(newValue);
1713 if (newval == NULL)
1714 return NULL;
1715 ENTER_TCL
1716 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1717 newval, flags);
1718 ENTER_OVERLAP
1719 if (!ok)
1720 Tkinter_Error(self);
1721 else {
1722 res = Py_None;
1723 Py_INCREF(res);
1724 }
1725 LEAVE_OVERLAP_TCL
1726 }
1727 else {
1728 PyErr_Clear();
1729 if (PyArg_ParseTuple(args, "ssO:setvar",
1730 &name1, &name2, &newValue)) {
1731 /* XXX must hold tcl lock already??? */
1732 newval = AsObj(newValue);
1733 ENTER_TCL
1734 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1735 ENTER_OVERLAP
1736 if (!ok)
1737 Tkinter_Error(self);
1738 else {
1739 res = Py_None;
1740 Py_INCREF(res);
1741 }
1742 LEAVE_OVERLAP_TCL
1743 }
1744 else {
1745 return NULL;
1746 }
1747 }
1748 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001749}
1750
1751static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001752Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001753{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001754 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001755}
1756
1757static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001758Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001759{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001760 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001761}
1762
Barry Warsawfa701a81997-01-16 00:15:11 +00001763
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001764
Guido van Rossum18468821994-06-20 07:49:28 +00001765static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001766GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001767{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001768 char *name1, *name2=NULL;
1769 PyObject *res = NULL;
1770 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001771
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001772 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1773 varname_converter, &name1, &name2))
1774 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001775
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001776 ENTER_TCL
1777 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1778 ENTER_OVERLAP
1779 if (tres == NULL) {
1780 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1781 } else {
1782 if (((TkappObject*)self)->wantobjects) {
1783 res = FromObj(self, tres);
1784 }
1785 else {
1786 res = PyString_FromString(Tcl_GetString(tres));
1787 }
1788 }
1789 LEAVE_OVERLAP_TCL
1790 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001791}
1792
1793static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001794Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001795{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001796 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001797}
1798
1799static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001800Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001801{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001802 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001803}
1804
Barry Warsawfa701a81997-01-16 00:15:11 +00001805
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001806
Guido van Rossum18468821994-06-20 07:49:28 +00001807static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001808UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001809{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001810 char *name1, *name2=NULL;
1811 int code;
1812 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001813
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001814 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1815 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001816
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001817 ENTER_TCL
1818 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1819 ENTER_OVERLAP
1820 if (code == TCL_ERROR)
1821 res = Tkinter_Error(self);
1822 else {
1823 Py_INCREF(Py_None);
1824 res = Py_None;
1825 }
1826 LEAVE_OVERLAP_TCL
1827 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001828}
1829
1830static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001831Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001832{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001833 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001834}
1835
1836static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001837Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001838{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001839 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001840}
1841
Barry Warsawfa701a81997-01-16 00:15:11 +00001842
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001843
Guido van Rossum18468821994-06-20 07:49:28 +00001844/** Tcl to Python **/
1845
1846static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001847Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001848{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001849 char *s;
1850 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001851
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001852 if (PyTuple_Size(args) == 1) {
1853 PyObject* o = PyTuple_GetItem(args, 0);
1854 if (PyInt_Check(o)) {
1855 Py_INCREF(o);
1856 return o;
1857 }
1858 }
1859 if (!PyArg_ParseTuple(args, "s:getint", &s))
1860 return NULL;
1861 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1862 return Tkinter_Error(self);
1863 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001864}
1865
1866static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001867Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001868{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001869 char *s;
1870 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001871
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001872 if (PyTuple_Size(args) == 1) {
1873 PyObject *o = PyTuple_GetItem(args, 0);
1874 if (PyFloat_Check(o)) {
1875 Py_INCREF(o);
1876 return o;
1877 }
1878 }
1879 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1880 return NULL;
1881 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1882 return Tkinter_Error(self);
1883 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001884}
1885
1886static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001887Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001888{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001889 char *s;
1890 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001891
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001892 if (PyTuple_Size(args) == 1) {
1893 PyObject *o = PyTuple_GetItem(args, 0);
1894 if (PyInt_Check(o)) {
1895 Py_INCREF(o);
1896 return o;
1897 }
1898 }
1899 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1900 return NULL;
1901 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1902 return Tkinter_Error(self);
1903 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001904}
1905
1906static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001907Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001908{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001909 char *s;
1910 PyObject *res = NULL;
1911 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001912
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001913 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1914 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001915
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001916 CHECK_TCL_APPARTMENT;
1917
1918 ENTER_TCL
1919 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1920 ENTER_OVERLAP
1921 if (retval == TCL_ERROR)
1922 res = Tkinter_Error(self);
1923 else
1924 res = Py_BuildValue("s", Tkapp_Result(self));
1925 LEAVE_OVERLAP_TCL
1926 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001927}
1928
1929static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001930Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001931{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001932 char *s;
1933 PyObject *res = NULL;
1934 int retval;
1935 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001936
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001937 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1938 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001939
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001940 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001941
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001942 ENTER_TCL
1943 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1944 ENTER_OVERLAP
1945 if (retval == TCL_ERROR)
1946 res = Tkinter_Error(self);
1947 else
1948 res = Py_BuildValue("l", v);
1949 LEAVE_OVERLAP_TCL
1950 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001951}
1952
1953static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001954Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001955{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001956 char *s;
1957 PyObject *res = NULL;
1958 double v;
1959 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001960
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001961 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1962 return NULL;
1963 CHECK_TCL_APPARTMENT;
1964 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1965 ENTER_TCL
1966 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1967 ENTER_OVERLAP
1968 PyFPE_END_PROTECT(retval)
1969 if (retval == TCL_ERROR)
1970 res = Tkinter_Error(self);
1971 else
1972 res = Py_BuildValue("d", v);
1973 LEAVE_OVERLAP_TCL
1974 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001975}
1976
1977static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001978Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001979{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001980 char *s;
1981 PyObject *res = NULL;
1982 int retval;
1983 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001984
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001985 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1986 return NULL;
1987 CHECK_TCL_APPARTMENT;
1988 ENTER_TCL
1989 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1990 ENTER_OVERLAP
1991 if (retval == TCL_ERROR)
1992 res = Tkinter_Error(self);
1993 else
1994 res = Py_BuildValue("i", v);
1995 LEAVE_OVERLAP_TCL
1996 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001997}
1998
Barry Warsawfa701a81997-01-16 00:15:11 +00001999
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002000
Guido van Rossum18468821994-06-20 07:49:28 +00002001static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002002Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002003{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002004 char *list;
2005 int argc;
2006 char **argv;
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002007 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002008 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002009
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002010 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2011 return NULL;
2012 if (PyTclObject_Check(arg)) {
2013 int objc;
2014 Tcl_Obj **objv;
2015 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2016 ((PyTclObject*)arg)->value,
2017 &objc, &objv) == TCL_ERROR) {
2018 return Tkinter_Error(self);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002019 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002020 if (!(v = PyTuple_New(objc)))
2021 return NULL;
2022 for (i = 0; i < objc; i++) {
2023 PyObject *s = FromObj(self, objv[i]);
2024 if (!s || PyTuple_SetItem(v, i, s)) {
2025 Py_DECREF(v);
2026 return NULL;
2027 }
2028 }
2029 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002030 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002031 if (PyTuple_Check(arg)) {
2032 Py_INCREF(arg);
2033 return arg;
2034 }
2035
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002036 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2037 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002038
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002039 if (Tcl_SplitList(Tkapp_Interp(self), list,
2040 &argc, &argv) == TCL_ERROR) {
2041 PyMem_Free(list);
2042 return Tkinter_Error(self);
2043 }
Guido van Rossum18468821994-06-20 07:49:28 +00002044
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002045 if (!(v = PyTuple_New(argc)))
2046 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002047
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002048 for (i = 0; i < argc; i++) {
2049 PyObject *s = PyString_FromString(argv[i]);
2050 if (!s || PyTuple_SetItem(v, i, s)) {
2051 Py_DECREF(v);
2052 v = NULL;
2053 goto finally;
2054 }
2055 }
Guido van Rossum18468821994-06-20 07:49:28 +00002056
Barry Warsawfa701a81997-01-16 00:15:11 +00002057 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002058 ckfree(FREECAST argv);
2059 PyMem_Free(list);
2060 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002061}
2062
2063static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002064Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002065{
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002066 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002067 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002068
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002069 if (!PyArg_ParseTuple(args, "O:split", &arg))
2070 return NULL;
2071 if (PyTclObject_Check(arg)) {
2072 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2073 int objc;
2074 Tcl_Obj **objv;
2075 int i;
2076 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2077 &objc, &objv) == TCL_ERROR) {
2078 return FromObj(self, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002079 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002080 if (objc == 0)
2081 return PyString_FromString("");
2082 if (objc == 1)
2083 return FromObj(self, objv[0]);
2084 if (!(v = PyTuple_New(objc)))
2085 return NULL;
2086 for (i = 0; i < objc; i++) {
2087 PyObject *s = FromObj(self, objv[i]);
2088 if (!s || PyTuple_SetItem(v, i, s)) {
2089 Py_DECREF(v);
2090 return NULL;
2091 }
2092 }
2093 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002094 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002095 if (PyTuple_Check(arg))
2096 return SplitObj(arg);
2097
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002098 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2099 return NULL;
2100 v = Split(list);
2101 PyMem_Free(list);
2102 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002103}
2104
2105static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002106Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002107{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002108 char *s = Merge(args);
2109 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002110
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002111 if (s) {
2112 res = PyString_FromString(s);
2113 ckfree(s);
2114 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002115
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002116 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002117}
2118
Barry Warsawfa701a81997-01-16 00:15:11 +00002119
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002120
Guido van Rossum18468821994-06-20 07:49:28 +00002121/** Tcl Command **/
2122
Guido van Rossum00d93061998-05-28 23:06:38 +00002123/* Client data struct */
2124typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002125 PyObject *self;
2126 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002127} PythonCmd_ClientData;
2128
2129static int
Fred Drake509d79a2000-07-08 04:04:38 +00002130PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002131{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002132 errorInCmd = 1;
2133 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2134 LEAVE_PYTHON
2135 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002136}
2137
Guido van Rossum18468821994-06-20 07:49:28 +00002138/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002139 * function or method.
2140 */
Guido van Rossum18468821994-06-20 07:49:28 +00002141static int
Fred Drake509d79a2000-07-08 04:04:38 +00002142PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002143{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002144 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2145 PyObject *func, *arg, *res;
2146 int i, rv;
2147 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002148
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002149 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002150
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002151 /* TBD: no error checking here since we know, via the
2152 * Tkapp_CreateCommand() that the client data is a two-tuple
2153 */
2154 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002155
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002156 /* Create argument list (argv1, ..., argvN) */
2157 if (!(arg = PyTuple_New(argc - 1)))
2158 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002159
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002160 for (i = 0; i < (argc - 1); i++) {
2161 PyObject *s = PyString_FromString(argv[i + 1]);
2162 if (!s || PyTuple_SetItem(arg, i, s)) {
2163 Py_DECREF(arg);
2164 return PythonCmd_Error(interp);
2165 }
2166 }
2167 res = PyEval_CallObject(func, arg);
2168 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002169
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002170 if (res == NULL)
2171 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002172
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002173 obj_res = AsObj(res);
2174 if (obj_res == NULL) {
2175 Py_DECREF(res);
2176 return PythonCmd_Error(interp);
2177 }
2178 else {
2179 Tcl_SetObjResult(interp, obj_res);
2180 rv = TCL_OK;
2181 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002182
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002183 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002184
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002185 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002186
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002187 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002188}
2189
2190static void
Fred Drake509d79a2000-07-08 04:04:38 +00002191PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002192{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002193 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002194
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002195 ENTER_PYTHON
2196 Py_XDECREF(data->self);
2197 Py_XDECREF(data->func);
2198 PyMem_DEL(data);
2199 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002200}
2201
Barry Warsawfa701a81997-01-16 00:15:11 +00002202
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002203
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002204
Guilherme Polo1972d162009-03-27 21:43:08 +00002205#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002206TCL_DECLARE_MUTEX(command_mutex)
2207
2208typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002209 Tcl_Event ev;
2210 Tcl_Interp* interp;
2211 char *name;
2212 int create;
2213 int *status;
2214 ClientData *data;
2215 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002216} CommandEvent;
2217
2218static int
2219Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002220{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002221 if (ev->create)
2222 *ev->status = Tcl_CreateCommand(
2223 ev->interp, ev->name, PythonCmd,
2224 ev->data, PythonCmdDelete) == NULL;
2225 else
2226 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2227 Tcl_MutexLock(&command_mutex);
2228 Tcl_ConditionNotify(ev->done);
2229 Tcl_MutexUnlock(&command_mutex);
2230 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002231}
Guilherme Polo1972d162009-03-27 21:43:08 +00002232#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002233
2234static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002235Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002236{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002237 TkappObject *self = (TkappObject*)selfptr;
2238 PythonCmd_ClientData *data;
2239 char *cmdName;
2240 PyObject *func;
2241 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002242
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002243 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2244 return NULL;
2245 if (!PyCallable_Check(func)) {
2246 PyErr_SetString(PyExc_TypeError, "command not callable");
2247 return NULL;
2248 }
Guido van Rossum18468821994-06-20 07:49:28 +00002249
Martin v. Löwisa9656492003-03-30 08:44:58 +00002250#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002251 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2252 !WaitForMainloop(self))
2253 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002254#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002255
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002256 data = PyMem_NEW(PythonCmd_ClientData, 1);
2257 if (!data)
2258 return PyErr_NoMemory();
2259 Py_INCREF(self);
2260 Py_INCREF(func);
2261 data->self = selfptr;
2262 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002263
2264#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002265 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2266 Tcl_Condition cond = NULL;
2267 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2268 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2269 ev->interp = self->interp;
2270 ev->create = 1;
2271 ev->name = cmdName;
2272 ev->data = (ClientData)data;
2273 ev->status = &err;
2274 ev->done = &cond;
2275 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2276 Tcl_ConditionFinalize(&cond);
2277 }
2278 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002279#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002280 {
2281 ENTER_TCL
2282 err = Tcl_CreateCommand(
2283 Tkapp_Interp(self), cmdName, PythonCmd,
2284 (ClientData)data, PythonCmdDelete) == NULL;
2285 LEAVE_TCL
2286 }
2287 if (err) {
2288 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2289 PyMem_DEL(data);
2290 return NULL;
2291 }
Guido van Rossum18468821994-06-20 07:49:28 +00002292
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002293 Py_INCREF(Py_None);
2294 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002295}
2296
Barry Warsawfa701a81997-01-16 00:15:11 +00002297
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002298
Guido van Rossum18468821994-06-20 07:49:28 +00002299static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002300Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002301{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002302 TkappObject *self = (TkappObject*)selfptr;
2303 char *cmdName;
2304 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002305
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002306 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2307 return NULL;
Guilherme Polo1972d162009-03-27 21:43:08 +00002308
2309#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002310 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2311 Tcl_Condition cond = NULL;
2312 CommandEvent *ev;
2313 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2314 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2315 ev->interp = self->interp;
2316 ev->create = 0;
2317 ev->name = cmdName;
2318 ev->status = &err;
2319 ev->done = &cond;
2320 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2321 &command_mutex);
2322 Tcl_ConditionFinalize(&cond);
2323 }
2324 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002325#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002326 {
2327 ENTER_TCL
2328 err = Tcl_DeleteCommand(self->interp, cmdName);
2329 LEAVE_TCL
2330 }
2331 if (err == -1) {
2332 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2333 return NULL;
2334 }
2335 Py_INCREF(Py_None);
2336 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002337}
2338
Barry Warsawfa701a81997-01-16 00:15:11 +00002339
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002340
Guido van Rossum00d93061998-05-28 23:06:38 +00002341#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002342/** File Handler **/
2343
Guido van Rossum00d93061998-05-28 23:06:38 +00002344typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002345 PyObject *func;
2346 PyObject *file;
2347 int id;
2348 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002349} FileHandler_ClientData;
2350
2351static FileHandler_ClientData *HeadFHCD;
2352
2353static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002354NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002355{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002356 FileHandler_ClientData *p;
2357 p = PyMem_NEW(FileHandler_ClientData, 1);
2358 if (p != NULL) {
2359 Py_XINCREF(func);
2360 Py_XINCREF(file);
2361 p->func = func;
2362 p->file = file;
2363 p->id = id;
2364 p->next = HeadFHCD;
2365 HeadFHCD = p;
2366 }
2367 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002368}
2369
2370static void
Fred Drake509d79a2000-07-08 04:04:38 +00002371DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002372{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002373 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002374
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002375 pp = &HeadFHCD;
2376 while ((p = *pp) != NULL) {
2377 if (p->id == id) {
2378 *pp = p->next;
2379 Py_XDECREF(p->func);
2380 Py_XDECREF(p->file);
2381 PyMem_DEL(p);
2382 }
2383 else
2384 pp = &p->next;
2385 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002386}
2387
Guido van Rossuma597dde1995-01-10 20:56:29 +00002388static void
Fred Drake509d79a2000-07-08 04:04:38 +00002389FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002390{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002391 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2392 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002393
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002394 ENTER_PYTHON
2395 func = data->func;
2396 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002397
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002398 arg = Py_BuildValue("(Oi)", file, (long) mask);
2399 res = PyEval_CallObject(func, arg);
2400 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002401
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002402 if (res == NULL) {
2403 errorInCmd = 1;
2404 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2405 }
2406 Py_XDECREF(res);
2407 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002408}
2409
Guido van Rossum18468821994-06-20 07:49:28 +00002410static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002411Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2412 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002413{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002414 FileHandler_ClientData *data;
2415 PyObject *file, *func;
2416 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002417
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002418 if (!self && Py_Py3kWarningFlag) {
2419 if (PyErr_Warn(PyExc_DeprecationWarning,
2420 "_tkinter.createfilehandler is gone in 3.x") < 0)
2421 return NULL;
2422 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002423
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002424 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2425 &file, &mask, &func))
2426 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002427
Martin v. Löwisa9656492003-03-30 08:44:58 +00002428#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002429 if (!self && !tcl_lock) {
2430 /* We don't have the Tcl lock since Tcl is threaded. */
2431 PyErr_SetString(PyExc_RuntimeError,
2432 "_tkinter.createfilehandler not supported "
2433 "for threaded Tcl");
2434 return NULL;
2435 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002436#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002437
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002438 if (self) {
2439 CHECK_TCL_APPARTMENT;
2440 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002441
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002442 tfile = PyObject_AsFileDescriptor(file);
2443 if (tfile < 0)
2444 return NULL;
2445 if (!PyCallable_Check(func)) {
2446 PyErr_SetString(PyExc_TypeError, "bad argument list");
2447 return NULL;
2448 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002449
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002450 data = NewFHCD(func, file, tfile);
2451 if (data == NULL)
2452 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002453
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002454 /* Ought to check for null Tcl_File object... */
2455 ENTER_TCL
2456 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2457 LEAVE_TCL
2458 Py_INCREF(Py_None);
2459 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002460}
2461
2462static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002463Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002464{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002465 PyObject *file;
2466 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002467
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002468 if (!self && Py_Py3kWarningFlag) {
2469 if (PyErr_Warn(PyExc_DeprecationWarning,
2470 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2471 return NULL;
2472 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002473
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002474 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2475 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002476
Martin v. Löwisa9656492003-03-30 08:44:58 +00002477#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002478 if (!self && !tcl_lock) {
2479 /* We don't have the Tcl lock since Tcl is threaded. */
2480 PyErr_SetString(PyExc_RuntimeError,
2481 "_tkinter.deletefilehandler not supported "
2482 "for threaded Tcl");
2483 return NULL;
2484 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002485#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002486
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002487 if (self) {
2488 CHECK_TCL_APPARTMENT;
2489 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002490
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002491 tfile = PyObject_AsFileDescriptor(file);
2492 if (tfile < 0)
2493 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002494
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002495 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002496
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002497 /* Ought to check for null Tcl_File object... */
2498 ENTER_TCL
2499 Tcl_DeleteFileHandler(tfile);
2500 LEAVE_TCL
2501 Py_INCREF(Py_None);
2502 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002503}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002504#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002505
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002506
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002507/**** Tktt Object (timer token) ****/
2508
Jeremy Hylton938ace62002-07-17 16:30:39 +00002509static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002510
Guido van Rossum00d93061998-05-28 23:06:38 +00002511typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002512 PyObject_HEAD
2513 Tcl_TimerToken token;
2514 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002515} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002516
2517static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002518Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002519{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002520 TkttObject *v = (TkttObject *)self;
2521 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002522
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002523 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2524 return NULL;
2525 if (v->token != NULL) {
2526 Tcl_DeleteTimerHandler(v->token);
2527 v->token = NULL;
2528 }
2529 if (func != NULL) {
2530 v->func = NULL;
2531 Py_DECREF(func);
2532 Py_DECREF(v); /* See Tktt_New() */
2533 }
2534 Py_INCREF(Py_None);
2535 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002536}
2537
2538static PyMethodDef Tktt_methods[] =
2539{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002540 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2541 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002542};
2543
2544static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002545Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002546{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002547 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002548
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002549 v = PyObject_New(TkttObject, &Tktt_Type);
2550 if (v == NULL)
2551 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002552
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002553 Py_INCREF(func);
2554 v->token = NULL;
2555 v->func = func;
2556
2557 /* Extra reference, deleted when called or when handler is deleted */
2558 Py_INCREF(v);
2559 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002560}
2561
2562static void
Fred Drake509d79a2000-07-08 04:04:38 +00002563Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002564{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002565 TkttObject *v = (TkttObject *)self;
2566 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002567
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002568 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002569
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002570 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002571}
2572
Guido van Rossum597ac201998-05-12 14:36:19 +00002573static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002574Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002575{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002576 TkttObject *v = (TkttObject *)self;
2577 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002578
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002579 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2580 v->func == NULL ? ", handler deleted" : "");
2581 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002582}
2583
2584static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002585Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002586{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002587 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002588}
2589
2590static PyTypeObject Tktt_Type =
2591{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002592 PyVarObject_HEAD_INIT(NULL, 0)
2593 "tktimertoken", /*tp_name */
2594 sizeof(TkttObject), /*tp_basicsize */
2595 0, /*tp_itemsize */
2596 Tktt_Dealloc, /*tp_dealloc */
2597 0, /*tp_print */
2598 Tktt_GetAttr, /*tp_getattr */
2599 0, /*tp_setattr */
2600 0, /*tp_compare */
2601 Tktt_Repr, /*tp_repr */
2602 0, /*tp_as_number */
2603 0, /*tp_as_sequence */
2604 0, /*tp_as_mapping */
2605 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002606};
2607
Barry Warsawfa701a81997-01-16 00:15:11 +00002608
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002609
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002610/** Timer Handler **/
2611
2612static void
Fred Drake509d79a2000-07-08 04:04:38 +00002613TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002614{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002615 TkttObject *v = (TkttObject *)clientData;
2616 PyObject *func = v->func;
2617 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002618
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002619 if (func == NULL)
2620 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002621
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002622 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002623
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002624 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002625
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002626 res = PyEval_CallObject(func, NULL);
2627 Py_DECREF(func);
2628 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002629
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002630 if (res == NULL) {
2631 errorInCmd = 1;
2632 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2633 }
2634 else
2635 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002636
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002637 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002638}
2639
2640static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002641Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002642{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002643 int milliseconds;
2644 PyObject *func;
2645 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002646
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002647 if (!self && Py_Py3kWarningFlag) {
2648 if (PyErr_Warn(PyExc_DeprecationWarning,
2649 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2650 return NULL;
2651 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002652
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002653 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2654 &milliseconds, &func))
2655 return NULL;
2656 if (!PyCallable_Check(func)) {
2657 PyErr_SetString(PyExc_TypeError, "bad argument list");
2658 return NULL;
2659 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002660
Martin v. Löwisa9656492003-03-30 08:44:58 +00002661#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002662 if (!self && !tcl_lock) {
2663 /* We don't have the Tcl lock since Tcl is threaded. */
2664 PyErr_SetString(PyExc_RuntimeError,
2665 "_tkinter.createtimerhandler not supported "
2666 "for threaded Tcl");
2667 return NULL;
2668 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002669#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002670
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002671 if (self) {
2672 CHECK_TCL_APPARTMENT;
2673 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002674
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002675 v = Tktt_New(func);
2676 if (v) {
2677 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2678 (ClientData)v);
2679 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002680
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002681 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002682}
2683
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002684
Guido van Rossum18468821994-06-20 07:49:28 +00002685/** Event Loop **/
2686
Guido van Rossum18468821994-06-20 07:49:28 +00002687static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002688Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002689{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002690 int threshold = 0;
2691 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002692#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002693 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002694#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002695
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002696 if (!self && Py_Py3kWarningFlag) {
2697 if (PyErr_Warn(PyExc_DeprecationWarning,
2698 "_tkinter.mainloop is gone in 3.x") < 0)
2699 return NULL;
2700 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002701
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002702 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2703 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002704
Martin v. Löwisa9656492003-03-30 08:44:58 +00002705#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002706 if (!self && !tcl_lock) {
2707 /* We don't have the Tcl lock since Tcl is threaded. */
2708 PyErr_SetString(PyExc_RuntimeError,
2709 "_tkinter.mainloop not supported "
2710 "for threaded Tcl");
2711 return NULL;
2712 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002713#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002714
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002715 if (self) {
2716 CHECK_TCL_APPARTMENT;
2717 self->dispatching = 1;
2718 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002719
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002720 quitMainLoop = 0;
2721 while (Tk_GetNumMainWindows() > threshold &&
2722 !quitMainLoop &&
2723 !errorInCmd)
2724 {
2725 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002726
2727#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002728 if (self && self->threaded) {
2729 /* Allow other Python threads to run. */
2730 ENTER_TCL
2731 result = Tcl_DoOneEvent(0);
2732 LEAVE_TCL
2733 }
2734 else {
2735 Py_BEGIN_ALLOW_THREADS
2736 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2737 tcl_tstate = tstate;
2738 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2739 tcl_tstate = NULL;
2740 if(tcl_lock)PyThread_release_lock(tcl_lock);
2741 if (result == 0)
2742 Sleep(Tkinter_busywaitinterval);
2743 Py_END_ALLOW_THREADS
2744 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002745#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002746 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002747#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002748
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002749 if (PyErr_CheckSignals() != 0) {
2750 if (self)
2751 self->dispatching = 0;
2752 return NULL;
2753 }
2754 if (result < 0)
2755 break;
2756 }
2757 if (self)
2758 self->dispatching = 0;
2759 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002760
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002761 if (errorInCmd) {
2762 errorInCmd = 0;
2763 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2764 excInCmd = valInCmd = trbInCmd = NULL;
2765 return NULL;
2766 }
2767 Py_INCREF(Py_None);
2768 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002769}
2770
2771static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002772Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002773{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002774 int flags = 0;
2775 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002776
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002777 if (!self && Py_Py3kWarningFlag) {
2778 if (PyErr_Warn(PyExc_DeprecationWarning,
2779 "_tkinter.dooneevent is gone in 3.x") < 0)
2780 return NULL;
2781 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002782
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002783 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2784 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002785
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002786 ENTER_TCL
2787 rv = Tcl_DoOneEvent(flags);
2788 LEAVE_TCL
2789 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002790}
2791
2792static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002793Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002794{
2795
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002796 if (!self && Py_Py3kWarningFlag) {
2797 if (PyErr_Warn(PyExc_DeprecationWarning,
2798 "_tkinter.quit is gone in 3.x") < 0)
2799 return NULL;
2800 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002801
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002802 if (!PyArg_ParseTuple(args, ":quit"))
2803 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002804
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002805 quitMainLoop = 1;
2806 Py_INCREF(Py_None);
2807 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002808}
2809
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002810static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002811Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002812{
2813
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002814 if (!PyArg_ParseTuple(args, ":interpaddr"))
2815 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002816
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002817 return PyInt_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002818}
2819
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002820static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002821Tkapp_TkInit(PyObject *self, PyObject *args)
2822{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002823 Tcl_Interp *interp = Tkapp_Interp(self);
2824 const char * _tk_exists = NULL;
2825 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002826
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002827#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002828 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2829 * first call failed.
2830 * To avoid the deadlock, we just refuse the second call through
2831 * a static variable.
2832 */
2833 if (tk_load_failed) {
2834 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2835 return NULL;
2836 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002837#endif
2838
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002839 /* We want to guard against calling Tk_Init() multiple times */
2840 CHECK_TCL_APPARTMENT;
2841 ENTER_TCL
2842 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2843 ENTER_OVERLAP
2844 if (err == TCL_ERROR) {
2845 /* This sets an exception, but we cannot return right
2846 away because we need to exit the overlap first. */
2847 Tkinter_Error(self);
2848 } else {
2849 _tk_exists = Tkapp_Result(self);
2850 }
2851 LEAVE_OVERLAP_TCL
2852 if (err == TCL_ERROR) {
2853 return NULL;
2854 }
2855 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2856 if (Tk_Init(interp) == TCL_ERROR) {
2857 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002858#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002859 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002860#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002861 return NULL;
2862 }
2863 }
2864 Py_INCREF(Py_None);
2865 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002866}
Barry Warsawfa701a81997-01-16 00:15:11 +00002867
Martin v. Löwisffad6332002-11-26 09:28:05 +00002868static PyObject *
2869Tkapp_WantObjects(PyObject *self, PyObject *args)
2870{
2871
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002872 int wantobjects = -1;
2873 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2874 return NULL;
2875 if (wantobjects == -1)
2876 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2877 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002878
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002879 Py_INCREF(Py_None);
2880 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002881}
2882
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002883static PyObject *
2884Tkapp_WillDispatch(PyObject *self, PyObject *args)
2885{
2886
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002887 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002888
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002889 Py_INCREF(Py_None);
2890 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002891}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002892
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002893
Guido van Rossum18468821994-06-20 07:49:28 +00002894/**** Tkapp Method List ****/
2895
2896static PyMethodDef Tkapp_methods[] =
2897{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002898 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2899 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2900 {"call", Tkapp_Call, METH_VARARGS},
2901 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2902 {"eval", Tkapp_Eval, METH_VARARGS},
2903 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2904 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2905 {"record", Tkapp_Record, METH_VARARGS},
2906 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2907 {"setvar", Tkapp_SetVar, METH_VARARGS},
2908 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2909 {"getvar", Tkapp_GetVar, METH_VARARGS},
2910 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2911 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2912 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2913 {"getint", Tkapp_GetInt, METH_VARARGS},
2914 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2915 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2916 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2917 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2918 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2919 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2920 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2921 {"split", Tkapp_Split, METH_VARARGS},
2922 {"merge", Tkapp_Merge, METH_VARARGS},
2923 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2924 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002925#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002926 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2927 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002928#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002929 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2930 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2931 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2932 {"quit", Tkapp_Quit, METH_VARARGS},
2933 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2934 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2935 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002936};
2937
Barry Warsawfa701a81997-01-16 00:15:11 +00002938
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002939
Guido van Rossum18468821994-06-20 07:49:28 +00002940/**** Tkapp Type Methods ****/
2941
2942static void
Fred Drake509d79a2000-07-08 04:04:38 +00002943Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002944{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002945 /*CHECK_TCL_APPARTMENT;*/
2946 ENTER_TCL
2947 Tcl_DeleteInterp(Tkapp_Interp(self));
2948 LEAVE_TCL
2949 PyObject_Del(self);
2950 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002951}
2952
2953static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002954Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002955{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002956 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002957}
2958
2959static PyTypeObject Tkapp_Type =
2960{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002961 PyVarObject_HEAD_INIT(NULL, 0)
2962 "tkapp", /*tp_name */
2963 sizeof(TkappObject), /*tp_basicsize */
2964 0, /*tp_itemsize */
2965 Tkapp_Dealloc, /*tp_dealloc */
2966 0, /*tp_print */
2967 Tkapp_GetAttr, /*tp_getattr */
2968 0, /*tp_setattr */
2969 0, /*tp_compare */
2970 0, /*tp_repr */
2971 0, /*tp_as_number */
2972 0, /*tp_as_sequence */
2973 0, /*tp_as_mapping */
2974 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002975};
2976
Barry Warsawfa701a81997-01-16 00:15:11 +00002977
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002978
Guido van Rossum18468821994-06-20 07:49:28 +00002979/**** Tkinter Module ****/
2980
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002981typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002982 PyObject* tuple;
2983 int size; /* current size */
2984 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002985} FlattenContext;
2986
2987static int
2988_bump(FlattenContext* context, int size)
2989{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002990 /* expand tuple to hold (at least) size new items.
2991 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002992
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002993 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002994
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002995 if (maxsize < context->size + size)
2996 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002997
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002998 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002999
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003000 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003001}
3002
3003static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003004_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003005{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003006 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003007
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003008 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003009
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003010 if (depth > 1000) {
3011 PyErr_SetString(PyExc_ValueError,
3012 "nesting too deep in _flatten");
3013 return 0;
3014 } else if (PyList_Check(item)) {
3015 size = PyList_GET_SIZE(item);
3016 /* preallocate (assume no nesting) */
3017 if (context->size + size > context->maxsize &&
3018 !_bump(context, size))
3019 return 0;
3020 /* copy items to output tuple */
3021 for (i = 0; i < size; i++) {
3022 PyObject *o = PyList_GET_ITEM(item, i);
3023 if (PyList_Check(o) || PyTuple_Check(o)) {
3024 if (!_flatten1(context, o, depth + 1))
3025 return 0;
3026 } else if (o != Py_None) {
3027 if (context->size + 1 > context->maxsize &&
3028 !_bump(context, 1))
3029 return 0;
3030 Py_INCREF(o);
3031 PyTuple_SET_ITEM(context->tuple,
3032 context->size++, o);
3033 }
3034 }
3035 } else if (PyTuple_Check(item)) {
3036 /* same, for tuples */
3037 size = PyTuple_GET_SIZE(item);
3038 if (context->size + size > context->maxsize &&
3039 !_bump(context, size))
3040 return 0;
3041 for (i = 0; i < size; i++) {
3042 PyObject *o = PyTuple_GET_ITEM(item, i);
3043 if (PyList_Check(o) || PyTuple_Check(o)) {
3044 if (!_flatten1(context, o, depth + 1))
3045 return 0;
3046 } else if (o != Py_None) {
3047 if (context->size + 1 > context->maxsize &&
3048 !_bump(context, 1))
3049 return 0;
3050 Py_INCREF(o);
3051 PyTuple_SET_ITEM(context->tuple,
3052 context->size++, o);
3053 }
3054 }
3055 } else {
3056 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3057 return 0;
3058 }
3059 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003060}
3061
3062static PyObject *
3063Tkinter_Flatten(PyObject* self, PyObject* args)
3064{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003065 FlattenContext context;
3066 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003067
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003068 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3069 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003070
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003071 context.maxsize = PySequence_Size(item);
3072 if (context.maxsize < 0)
3073 return NULL;
3074 if (context.maxsize == 0)
3075 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003076
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003077 context.tuple = PyTuple_New(context.maxsize);
3078 if (!context.tuple)
3079 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003080
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003081 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003082
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003083 if (!_flatten1(&context, item,0))
3084 return NULL;
3085
3086 if (_PyTuple_Resize(&context.tuple, context.size))
3087 return NULL;
3088
3089 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003090}
3091
Guido van Rossum18468821994-06-20 07:49:28 +00003092static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003093Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003094{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003095 char *screenName = NULL;
3096 char *baseName = NULL;
3097 char *className = NULL;
3098 int interactive = 0;
3099 int wantobjects = 0;
3100 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3101 int sync = 0; /* pass -sync to wish */
3102 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003103
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003104 baseName = strrchr(Py_GetProgramName(), '/');
3105 if (baseName != NULL)
3106 baseName++;
3107 else
3108 baseName = Py_GetProgramName();
3109 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003110
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003111 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3112 &screenName, &baseName, &className,
3113 &interactive, &wantobjects, &wantTk,
3114 &sync, &use))
3115 return NULL;
3116
3117 return (PyObject *) Tkapp_New(screenName, baseName, className,
3118 interactive, wantobjects, wantTk,
3119 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003120}
3121
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003122static PyObject *
3123Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3124{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003125 int new_val;
3126 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3127 return NULL;
3128 if (new_val < 0) {
3129 PyErr_SetString(PyExc_ValueError,
3130 "busywaitinterval must be >= 0");
3131 return NULL;
3132 }
3133 Tkinter_busywaitinterval = new_val;
3134 Py_INCREF(Py_None);
3135 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003136}
3137
3138static char setbusywaitinterval_doc[] =
3139"setbusywaitinterval(n) -> None\n\
3140\n\
3141Set the busy-wait interval in milliseconds between successive\n\
3142calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3143It should be set to a divisor of the maximum time between\n\
3144frames in an animation.";
3145
3146static PyObject *
3147Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3148{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003149 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003150}
3151
3152static char getbusywaitinterval_doc[] =
3153"getbusywaitinterval() -> int\n\
3154\n\
3155Return the current busy-wait interval between successive\n\
3156calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3157
Guido van Rossum18468821994-06-20 07:49:28 +00003158static PyMethodDef moduleMethods[] =
3159{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003160 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3161 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003162#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003163 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3164 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003165#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003166 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3167 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3168 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3169 {"quit", Tkapp_Quit, METH_VARARGS},
3170 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3171 setbusywaitinterval_doc},
3172 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3173 METH_NOARGS, getbusywaitinterval_doc},
3174 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003175};
3176
Guido van Rossum7bf15641998-05-22 18:28:17 +00003177#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003178
3179static int stdin_ready = 0;
3180
Guido van Rossumad4db171998-06-13 13:56:28 +00003181#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003182static void
Fred Drake509d79a2000-07-08 04:04:38 +00003183MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003184{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003185 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003186}
Guido van Rossumad4db171998-06-13 13:56:28 +00003187#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003188
Martin v. Löwisa9656492003-03-30 08:44:58 +00003189#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003190static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003191#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003192
Guido van Rossum18468821994-06-20 07:49:28 +00003193static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003194EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003195{
Guido van Rossumad4db171998-06-13 13:56:28 +00003196#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003197 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003198#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003199#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003200 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003201#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003202 stdin_ready = 0;
3203 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003204#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003205 tfile = fileno(stdin);
3206 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003207#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003208 while (!errorInCmd && !stdin_ready) {
3209 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003210#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003211 if (_kbhit()) {
3212 stdin_ready = 1;
3213 break;
3214 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003215#endif
3216#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003217 Py_BEGIN_ALLOW_THREADS
3218 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3219 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003220
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003221 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003222
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003223 tcl_tstate = NULL;
3224 if(tcl_lock)PyThread_release_lock(tcl_lock);
3225 if (result == 0)
3226 Sleep(Tkinter_busywaitinterval);
3227 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003228#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003229 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003230#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003231
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003232 if (result < 0)
3233 break;
3234 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003235#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003236 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003237#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003238 if (errorInCmd) {
3239 errorInCmd = 0;
3240 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3241 excInCmd = valInCmd = trbInCmd = NULL;
3242 PyErr_Print();
3243 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003244#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003245 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003246#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003247 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003248}
Guido van Rossum18468821994-06-20 07:49:28 +00003249
Guido van Rossum00d93061998-05-28 23:06:38 +00003250#endif
3251
Guido van Rossum7bf15641998-05-22 18:28:17 +00003252static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003253EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003254{
Guido van Rossum00d93061998-05-28 23:06:38 +00003255#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003256 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003257#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003258 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003259#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003260 PyOS_InputHook = EventHook;
3261 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003262#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003263}
3264
3265static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003266DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003267{
Guido van Rossum00d93061998-05-28 23:06:38 +00003268#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003269 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3270 PyOS_InputHook = NULL;
3271 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003272#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003273}
3274
Barry Warsawfa701a81997-01-16 00:15:11 +00003275
3276/* all errors will be checked in one fell swoop in init_tkinter() */
3277static void
Fred Drake509d79a2000-07-08 04:04:38 +00003278ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003279{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003280 PyObject *v = PyInt_FromLong(val);
3281 if (v) {
3282 PyDict_SetItemString(d, name, v);
3283 Py_DECREF(v);
3284 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003285}
3286static void
Fred Drake509d79a2000-07-08 04:04:38 +00003287ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003288{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003289 PyObject *v = PyString_FromString(val);
3290 if (v) {
3291 PyDict_SetItemString(d, name, v);
3292 Py_DECREF(v);
3293 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003294}
3295
3296
Mark Hammond62b1ab12002-07-23 06:31:15 +00003297PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003298init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003299{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003300 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003301
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003302 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003303
3304#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003305 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003306#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003307
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003308 m = Py_InitModule("_tkinter", moduleMethods);
3309 if (m == NULL)
3310 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003311
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003312 d = PyModule_GetDict(m);
3313 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3314 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003315
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003316 ins_long(d, "READABLE", TCL_READABLE);
3317 ins_long(d, "WRITABLE", TCL_WRITABLE);
3318 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3319 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3320 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3321 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3322 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3323 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3324 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3325 ins_string(d, "TK_VERSION", TK_VERSION);
3326 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003327
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003328 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003329
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003330 Py_TYPE(&Tktt_Type) = &PyType_Type;
3331 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003332
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003333 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3334 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003335
3336#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003337 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3338 * start waking up. Note that Tcl_FindExecutable will do this, this
3339 * code must be above it! The original warning from
3340 * tkMacOSXAppInit.c is copied below.
3341 *
3342 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3343 * Tcl interpreter for now. It probably should work to do this
3344 * in the other order, but for now it doesn't seem to.
3345 *
3346 */
3347 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003348#endif
3349
3350
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003351 /* This helps the dynamic loader; in Unicode aware Tcl versions
3352 it also helps Tcl find its encodings. */
3353 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003354
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003355 if (PyErr_Occurred())
3356 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003357
Guido van Rossum43ff8681998-07-14 18:02:13 +00003358#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003359 /* This was not a good idea; through <Destroy> bindings,
3360 Tcl_Finalize() may invoke Python code but at that point the
3361 interpreter and thread state have already been destroyed! */
3362 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003363#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003364
Guido van Rossum18468821994-06-20 07:49:28 +00003365}