blob: 93e4a985bcdbcae0286fe32ae1dc549fd9d1f0fa [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
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000012 Only Tcl/Tk 8.2 and later are supported. Older versions are not
13 supported. (Use Python 2.2 if you cannot upgrade your Tcl/Tk
Guido van Rossuma80649b2000-03-28 20:07:05 +000014 libraries.)
15*/
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
Martin v. Löwis71e25a02002-10-01 18:08:06 +000050/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
51 making _tkinter correct for this API means to break earlier
52 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
53 earlier versions. Once Tcl releases before 8.4 don't need to be supported
54 anymore, this should go. */
55#define USE_COMPAT_CONST
56
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000057/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
58 it always; if Tcl is not threaded, the thread functions in
59 Tcl are empty. */
60#define TCL_THREADS
61
Jack Jansencb852442001-12-09 23:15:56 +000062#ifdef TK_FRAMEWORK
63#include <Tcl/tcl.h>
64#include <Tk/tk.h>
65#else
Guido van Rossum18468821994-06-20 07:49:28 +000066#include <tcl.h>
67#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000068#endif
Guido van Rossum18468821994-06-20 07:49:28 +000069
Jason Tishlerbbe89612002-12-31 20:30:46 +000070/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000071#ifndef CONST84_RETURN
72#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000073#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000074#define CONST
75#endif
76
Guido van Rossum3e819a71997-08-01 19:29:02 +000077#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
78
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000079#if TKMAJORMINOR < 8002
80#error "Tk older than 8.2 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000081#endif
82
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000083/* Unicode conversion assumes that Tcl_UniChar is two bytes.
84 We cannot test this directly, so we test UTF-8 size instead,
85 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000086 either UTF-16 or UCS-4.
87 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
88 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
89 as well.
90*/
91#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000092#error "unsupported Tcl configuration"
93#endif
94
Jack Janseneddc1442003-11-20 01:44:59 +000095#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000096#define HAVE_CREATEFILEHANDLER
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#ifdef HAVE_CREATEFILEHANDLER
100
Neal Norwitzd948a432006-01-08 01:08:55 +0000101/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
102 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
103#ifndef TCL_UNIX_FD
104# ifdef TCL_WIN_SOCKET
105# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
106# else
107# define TCL_UNIX_FD 1
108# endif
109#endif
110
Guido van Rossum00d93061998-05-28 23:06:38 +0000111/* Tcl_CreateFileHandler() changed several times; these macros deal with the
112 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
113 Unix, only because Jack added it back); when available on Windows, it only
114 applies to sockets. */
115
Guido van Rossum7bf15641998-05-22 18:28:17 +0000116#ifdef MS_WINDOWS
117#define FHANDLETYPE TCL_WIN_SOCKET
118#else
119#define FHANDLETYPE TCL_UNIX_FD
120#endif
121
Guido van Rossum00d93061998-05-28 23:06:38 +0000122/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
123 which uses this to handle Tcl events while the user is typing commands. */
124
125#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000126#define WAIT_FOR_STDIN
127#endif
128
Guido van Rossum00d93061998-05-28 23:06:38 +0000129#endif /* HAVE_CREATEFILEHANDLER */
130
Guido van Rossumad4db171998-06-13 13:56:28 +0000131#ifdef MS_WINDOWS
132#include <conio.h>
133#define WAIT_FOR_STDIN
134#endif
135
Guido van Rossum00d93061998-05-28 23:06:38 +0000136#ifdef WITH_THREAD
137
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000138/* The threading situation is complicated. Tcl is not thread-safe, except
139 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000140 So we need to use a lock around all uses of Tcl. Previously, the Python
141 interpreter lock was used for this. However, this causes problems when
142 other Python threads need to run while Tcl is blocked waiting for events.
143
144 To solve this problem, a separate lock for Tcl is introduced. Holding it
145 is incompatible with holding Python's interpreter lock. The following four
146 macros manipulate both locks together.
147
148 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
149 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
150 that could call an event handler, or otherwise affect the state of a Tcl
151 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000152 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000153 released and the lock for Tcl has been acquired.
154
Guido van Rossum5e977831998-06-15 14:03:52 +0000155 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
156 (For example, when transferring data from the Tcl interpreter result to a
157 Python string object.) This can be done by using different macros to close
158 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
159 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
160 releases the Tcl lock.
161
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000162 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000163 handlers when the handler needs to use Python. Such event handlers are
164 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000165 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000166 the Python interpreter lock, restoring the appropriate thread state, and
167 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
168 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000169 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000170
171 These locks expand to several statements and brackets; they should not be
172 used in branches of if statements and the like.
173
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000174 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
175 only valid in the thread that created it, and all Tk activity must happen in this
176 thread, also. That means that the mainloop must be invoked in the thread that
177 created the interpreter. Invoking commands from other threads is possible;
178 _tkinter will queue an event for the interpreter thread, which will then
179 execute the command and pass back the result. If the main thread is not in the
180 mainloop, and invoking commands causes an exception; if the main loop is running
181 but not processing events, the command invocation will block.
182
183 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
184 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
185 threads. So we use the Tcl TLS API.
186
Guido van Rossum00d93061998-05-28 23:06:38 +0000187*/
188
Guido van Rossum65d5b571998-12-21 19:32:43 +0000189static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000190
191#ifdef TCL_THREADS
192static Tcl_ThreadDataKey state_key;
193typedef PyThreadState *ThreadSpecificData;
194#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
195#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000196static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000197#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000198
199#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000200 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000201 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
203#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000204 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000205
Guido van Rossum62320c91998-06-15 04:36:09 +0000206#define ENTER_OVERLAP \
207 Py_END_ALLOW_THREADS
208
209#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000210 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000211
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000212#define ENTER_PYTHON \
213 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000214 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
216#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000217 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000218 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
219
220#define CHECK_TCL_APPARTMENT \
221 if (((TkappObject *)self)->threaded && \
222 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
223 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
224 return 0; \
225 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000226
227#else
228
229#define ENTER_TCL
230#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000231#define ENTER_OVERLAP
232#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000233#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000234#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000235#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000236
237#endif
238
Guido van Rossum97867b21996-08-08 19:09:53 +0000239#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000240#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000241#endif
242
Guido van Rossum18468821994-06-20 07:49:28 +0000243/**** Tkapp Object Declaration ****/
244
Jeremy Hylton938ace62002-07-17 16:30:39 +0000245static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000246
Guido van Rossum00d93061998-05-28 23:06:38 +0000247typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000248 PyObject_HEAD
249 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000250 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000251 int threaded; /* True if tcl_platform[threaded] */
252 Tcl_ThreadId thread_id;
253 int dispatching;
254 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000255 So we cache interesting types here. */
256 Tcl_ObjType *BooleanType;
257 Tcl_ObjType *ByteArrayType;
258 Tcl_ObjType *DoubleType;
259 Tcl_ObjType *IntType;
260 Tcl_ObjType *ListType;
261 Tcl_ObjType *ProcBodyType;
262 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000263} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000264
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000265#define Tkapp_Check(v) (Py_Type(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000266#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000267#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000268
Guido van Rossum35d43371997-08-02 00:09:09 +0000269#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000270(void *) v, Py_Refcnt(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000271
Barry Warsawfa701a81997-01-16 00:15:11 +0000272
273
Guido van Rossum18468821994-06-20 07:49:28 +0000274/**** Error Handling ****/
275
276static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000277static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000278static int errorInCmd = 0;
279static PyObject *excInCmd;
280static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000281static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
284
Guido van Rossum18468821994-06-20 07:49:28 +0000285static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000286Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000287{
Barry Warsawfa701a81997-01-16 00:15:11 +0000288 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
289 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000290}
291
Barry Warsawfa701a81997-01-16 00:15:11 +0000292
Barry Warsawfa701a81997-01-16 00:15:11 +0000293
Guido van Rossum18468821994-06-20 07:49:28 +0000294/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000295
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000296static int Tkinter_busywaitinterval = 20;
297
Guido van Rossum00d93061998-05-28 23:06:38 +0000298#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000299#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000300
Guido van Rossum00d93061998-05-28 23:06:38 +0000301/* Millisecond sleep() for Unix platforms. */
302
303static void
Fred Drake509d79a2000-07-08 04:04:38 +0000304Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000305{
306 /* XXX Too bad if you don't have select(). */
307 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000308 t.tv_sec = milli/1000;
309 t.tv_usec = (milli%1000) * 1000;
310 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
311}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000312#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000313
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000314/* Wait up to 1s for the mainloop to come up. */
315
316static int
317WaitForMainloop(TkappObject* self)
318{
319 int i;
320 for (i = 0; i < 10; i++) {
321 if (self->dispatching)
322 return 1;
323 Py_BEGIN_ALLOW_THREADS
324 Sleep(100);
325 Py_END_ALLOW_THREADS
326 }
327 if (self->dispatching)
328 return 1;
329 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
330 return 0;
331}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000332#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000333
Guido van Rossum00d93061998-05-28 23:06:38 +0000334
Guido van Rossum18468821994-06-20 07:49:28 +0000335static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000336AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000337{
Guido van Rossum35d43371997-08-02 00:09:09 +0000338 if (PyString_Check(value))
339 return PyString_AsString(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000340 else if (PyUnicode_Check(value)) {
341 PyObject *v = PyUnicode_AsUTF8String(value);
342 if (v == NULL)
343 return NULL;
344 if (PyList_Append(tmp, v) != 0) {
345 Py_DECREF(v);
346 return NULL;
347 }
348 Py_DECREF(v);
349 return PyString_AsString(v);
350 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000351 else {
352 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000353 if (v == NULL)
354 return NULL;
355 if (PyList_Append(tmp, v) != 0) {
356 Py_DECREF(v);
357 return NULL;
358 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000359 Py_DECREF(v);
360 return PyString_AsString(v);
361 }
Guido van Rossum18468821994-06-20 07:49:28 +0000362}
363
Barry Warsawfa701a81997-01-16 00:15:11 +0000364
365
Guido van Rossum18468821994-06-20 07:49:28 +0000366#define ARGSZ 64
367
368static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000369Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000370{
Barry Warsawfa701a81997-01-16 00:15:11 +0000371 PyObject *tmp = NULL;
372 char *argvStore[ARGSZ];
373 char **argv = NULL;
374 int fvStore[ARGSZ];
375 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000376 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000377 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000378
Barry Warsawfa701a81997-01-16 00:15:11 +0000379 if (!(tmp = PyList_New(0)))
380 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000381
Barry Warsawfa701a81997-01-16 00:15:11 +0000382 argv = argvStore;
383 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000384
Barry Warsawfa701a81997-01-16 00:15:11 +0000385 if (args == NULL)
386 argc = 0;
387
388 else if (!PyTuple_Check(args)) {
389 argc = 1;
390 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000391 if (!(argv[0] = AsString(args, tmp)))
392 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000393 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000394 else {
395 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000396
Barry Warsawfa701a81997-01-16 00:15:11 +0000397 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000398 argv = (char **)ckalloc(argc * sizeof(char *));
399 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000400 if (argv == NULL || fv == NULL) {
401 PyErr_NoMemory();
402 goto finally;
403 }
404 }
405
406 for (i = 0; i < argc; i++) {
407 PyObject *v = PyTuple_GetItem(args, i);
408 if (PyTuple_Check(v)) {
409 fv[i] = 1;
410 if (!(argv[i] = Merge(v)))
411 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000412 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000413 }
414 else if (v == Py_None) {
415 argc = i;
416 break;
417 }
418 else {
419 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000420 if (!(argv[i] = AsString(v, tmp)))
421 goto finally;
422 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000423 }
424 }
Guido van Rossum18468821994-06-20 07:49:28 +0000425 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000426 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000427 if (res == NULL)
428 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000429
Barry Warsawfa701a81997-01-16 00:15:11 +0000430 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000431 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000432 if (fv[i]) {
433 ckfree(argv[i]);
434 }
435 if (argv != argvStore)
436 ckfree(FREECAST argv);
437 if (fv != fvStore)
438 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000439
Barry Warsawfa701a81997-01-16 00:15:11 +0000440 Py_DECREF(tmp);
441 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000442}
443
Barry Warsawfa701a81997-01-16 00:15:11 +0000444
445
Guido van Rossum18468821994-06-20 07:49:28 +0000446static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000447Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000448{
Barry Warsawfa701a81997-01-16 00:15:11 +0000449 int argc;
450 char **argv;
451 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000452
Barry Warsawfa701a81997-01-16 00:15:11 +0000453 if (list == NULL) {
454 Py_INCREF(Py_None);
455 return Py_None;
456 }
Guido van Rossum18468821994-06-20 07:49:28 +0000457
Guido van Rossum00d93061998-05-28 23:06:38 +0000458 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000459 /* Not a list.
460 * Could be a quoted string containing funnies, e.g. {"}.
461 * Return the string itself.
462 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000463 return PyString_FromString(list);
464 }
Guido van Rossum18468821994-06-20 07:49:28 +0000465
Barry Warsawfa701a81997-01-16 00:15:11 +0000466 if (argc == 0)
467 v = PyString_FromString("");
468 else if (argc == 1)
469 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000470 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000471 int i;
472 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000473
Barry Warsawfa701a81997-01-16 00:15:11 +0000474 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000475 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000476 Py_DECREF(v);
477 v = NULL;
478 break;
479 }
480 PyTuple_SetItem(v, i, w);
481 }
482 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000483 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000484 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000485}
486
Martin v. Löwisffad6332002-11-26 09:28:05 +0000487/* In some cases, Tcl will still return strings that are supposed to be
488 lists. SplitObj walks through a nested tuple, finding string objects that
489 need to be split. */
490
491PyObject *
492SplitObj(PyObject *arg)
493{
494 if (PyTuple_Check(arg)) {
495 int i, size;
496 PyObject *elem, *newelem, *result;
497
498 size = PyTuple_Size(arg);
499 result = NULL;
500 /* Recursively invoke SplitObj for all tuple items.
501 If this does not return a new object, no action is
502 needed. */
503 for(i = 0; i < size; i++) {
504 elem = PyTuple_GetItem(arg, i);
505 newelem = SplitObj(elem);
506 if (!newelem) {
507 Py_XDECREF(result);
508 return NULL;
509 }
510 if (!result) {
511 int k;
512 if (newelem == elem) {
513 Py_DECREF(newelem);
514 continue;
515 }
516 result = PyTuple_New(size);
517 if (!result)
518 return NULL;
519 for(k = 0; k < i; k++) {
520 elem = PyTuple_GetItem(arg, k);
521 Py_INCREF(elem);
522 PyTuple_SetItem(result, k, elem);
523 }
524 }
525 PyTuple_SetItem(result, i, newelem);
526 }
527 if (result)
528 return result;
529 /* Fall through, returning arg. */
530 }
531 else if (PyString_Check(arg)) {
532 int argc;
533 char **argv;
534 char *list = PyString_AsString(arg);
535
536 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
537 Py_INCREF(arg);
538 return arg;
539 }
540 Tcl_Free(FREECAST argv);
541 if (argc > 1)
542 return Split(PyString_AsString(arg));
543 /* Fall through, returning arg. */
544 }
545 Py_INCREF(arg);
546 return arg;
547}
Barry Warsawfa701a81997-01-16 00:15:11 +0000548
549
Guido van Rossum18468821994-06-20 07:49:28 +0000550/**** Tkapp Object ****/
551
552#ifndef WITH_APPINIT
553int
Fred Drake509d79a2000-07-08 04:04:38 +0000554Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000555{
Barry Warsawfa701a81997-01-16 00:15:11 +0000556 Tk_Window main;
David Aschere2b4b322004-02-18 05:59:53 +0000557 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000558
Barry Warsawfa701a81997-01-16 00:15:11 +0000559 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000560 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000561 return TCL_ERROR;
562 }
David Aschere2b4b322004-02-18 05:59:53 +0000563 _tkinter_skip_tk_init = Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
564 if (_tkinter_skip_tk_init == NULL || strcmp(_tkinter_skip_tk_init, "1") != 0) {
565 main = Tk_MainWindow(interp);
566 if (Tk_Init(interp) == TCL_ERROR) {
567 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
568 return TCL_ERROR;
569 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000570 }
571 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000572}
573#endif /* !WITH_APPINIT */
574
Guido van Rossum18468821994-06-20 07:49:28 +0000575
Barry Warsawfa701a81997-01-16 00:15:11 +0000576
577
578/* Initialize the Tk application; see the `main' function in
579 * `tkMain.c'.
580 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000581
Thomas Wouters58d05102000-07-24 14:43:35 +0000582static void EnableEventHook(void); /* Forward */
583static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000584
Barry Warsawfa701a81997-01-16 00:15:11 +0000585static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000586Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000587 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000588{
589 TkappObject *v;
590 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000591
Guido van Rossumb18618d2000-05-03 23:44:39 +0000592 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000593 if (v == NULL)
594 return NULL;
595
596 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000597 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000598 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
599 TCL_GLOBAL_ONLY) != NULL;
600 v->thread_id = Tcl_GetCurrentThread();
601 v->dispatching = 0;
602
603#ifndef TCL_THREADS
604 if (v->threaded) {
605 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
606 Py_DECREF(v);
607 return 0;
608 }
609#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000610#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000611 if (v->threaded && tcl_lock) {
612 /* If Tcl is threaded, we don't need the lock. */
613 PyThread_free_lock(tcl_lock);
614 tcl_lock = NULL;
615 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000616#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000617
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000618 v->BooleanType = Tcl_GetObjType("boolean");
619 v->ByteArrayType = Tcl_GetObjType("bytearray");
620 v->DoubleType = Tcl_GetObjType("double");
621 v->IntType = Tcl_GetObjType("int");
622 v->ListType = Tcl_GetObjType("list");
623 v->ProcBodyType = Tcl_GetObjType("procbody");
624 v->StringType = Tcl_GetObjType("string");
625
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000626 /* Delete the 'exit' command, which can screw things up */
627 Tcl_DeleteCommand(v->interp, "exit");
628
Barry Warsawfa701a81997-01-16 00:15:11 +0000629 if (screenName != NULL)
630 Tcl_SetVar2(v->interp, "env", "DISPLAY",
631 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000632
Barry Warsawfa701a81997-01-16 00:15:11 +0000633 if (interactive)
634 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
635 else
636 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000637
Barry Warsawfa701a81997-01-16 00:15:11 +0000638 /* This is used to get the application class for Tk 4.1 and up */
639 argv0 = (char*)ckalloc(strlen(className) + 1);
640 if (!argv0) {
641 PyErr_NoMemory();
642 Py_DECREF(v);
643 return NULL;
644 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000645
Barry Warsawfa701a81997-01-16 00:15:11 +0000646 strcpy(argv0, className);
Neal Norwitz9dbc7dd2005-12-19 06:08:59 +0000647 if (isupper(Py_CHARMASK(argv0[0])))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000648 argv0[0] = tolower(Py_CHARMASK(argv0[0]));
Barry Warsawfa701a81997-01-16 00:15:11 +0000649 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
650 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000651
David Aschere2b4b322004-02-18 05:59:53 +0000652 if (! wantTk) {
653 Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
654 }
655
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000656 /* some initial arguments need to be in argv */
657 if (sync || use) {
Tim Peters51fa3b72004-08-04 02:16:48 +0000658 char *args;
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000659 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000660
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000661 if (sync)
662 len += sizeof "-sync";
663 if (use)
664 len += strlen(use) + sizeof "-use ";
665
Tim Peters51fa3b72004-08-04 02:16:48 +0000666 args = (char*)ckalloc(len);
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000667 if (!args) {
668 PyErr_NoMemory();
669 Py_DECREF(v);
670 return NULL;
671 }
672
673 args[0] = '\0';
674 if (sync)
675 strcat(args, "-sync");
676 if (use) {
677 if (sync)
678 strcat(args, " ");
679 strcat(args, "-use ");
680 strcat(args, use);
681 }
682
683 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
684 ckfree(args);
685 }
686
Thomas Woutersa74a84d2006-03-07 14:04:31 +0000687 if (Tcl_AppInit(v->interp) != TCL_OK) {
688 PyObject *result = Tkinter_Error((PyObject *)v);
689 Py_DECREF((PyObject *)v);
690 return (TkappObject *)result;
691 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000692
Guido van Rossum7bf15641998-05-22 18:28:17 +0000693 EnableEventHook();
694
Barry Warsawfa701a81997-01-16 00:15:11 +0000695 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000696}
697
Barry Warsawfa701a81997-01-16 00:15:11 +0000698
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000699static void
700Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
701 Tcl_Condition *cond, Tcl_Mutex *mutex)
702{
703 Py_BEGIN_ALLOW_THREADS;
704 Tcl_MutexLock(mutex);
705 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
706 Tcl_ThreadAlert(self->thread_id);
707 Tcl_ConditionWait(cond, mutex, NULL);
708 Tcl_MutexUnlock(mutex);
709 Py_END_ALLOW_THREADS
710}
711
Barry Warsawfa701a81997-01-16 00:15:11 +0000712
Guido van Rossum18468821994-06-20 07:49:28 +0000713/** Tcl Eval **/
714
Martin v. Löwisffad6332002-11-26 09:28:05 +0000715typedef struct {
716 PyObject_HEAD
717 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000718 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000719} PyTclObject;
720
Neal Norwitz227b5332006-03-22 09:28:35 +0000721static PyTypeObject PyTclObject_Type;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000722#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
723
724static PyObject *
725newPyTclObject(Tcl_Obj *arg)
726{
727 PyTclObject *self;
728 self = PyObject_New(PyTclObject, &PyTclObject_Type);
729 if (self == NULL)
730 return NULL;
731 Tcl_IncrRefCount(arg);
732 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000733 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000734 return (PyObject*)self;
735}
736
737static void
738PyTclObject_dealloc(PyTclObject *self)
739{
740 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000741 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000742 PyObject_Del(self);
743}
744
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000745static char*
746PyTclObject_TclString(PyObject *self)
747{
748 return Tcl_GetString(((PyTclObject*)self)->value);
749}
750
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000751/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000752PyDoc_STRVAR(PyTclObject_string__doc__,
Walter Dörwalda1884662007-07-12 12:16:02 +0000753"the string representation of this object, either as str8 or str");
Martin v. Löwis39195712003-01-04 00:33:13 +0000754
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000755static PyObject *
756PyTclObject_string(PyTclObject *self, void *ignored)
757{
758 char *s;
759 int i, len;
760 if (!self->string) {
761 s = Tcl_GetStringFromObj(self->value, &len);
762 for (i = 0; i < len; i++)
763 if (s[i] & 0x80)
764 break;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000765 if (i == len)
766 /* It is an ASCII string. */
767 self->string = PyString_FromStringAndSize(s, len);
768 else {
769 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
770 if (!self->string) {
771 PyErr_Clear();
772 self->string = PyString_FromStringAndSize(s, len);
773 }
774 }
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000775 if (!self->string)
776 return NULL;
777 }
778 Py_INCREF(self->string);
779 return self->string;
780}
781
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000782static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000783PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000784{
785 char *s;
786 int len;
787 if (self->string && PyUnicode_Check(self->string)) {
788 Py_INCREF(self->string);
789 return self->string;
790 }
791 /* XXX Could chache result if it is non-ASCII. */
792 s = Tcl_GetStringFromObj(self->value, &len);
793 return PyUnicode_DecodeUTF8(s, len, "strict");
794}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000795
Martin v. Löwisffad6332002-11-26 09:28:05 +0000796static PyObject *
797PyTclObject_repr(PyTclObject *self)
798{
Walter Dörwald7569dfe2007-05-19 21:49:49 +0000799 return PyUnicode_FromFormat("<%s object at %p>",
800 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000801}
802
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000803static int
804PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
805{
806 int res;
807 res = strcmp(Tcl_GetString(self->value),
808 Tcl_GetString(other->value));
809 if (res < 0) return -1;
810 if (res > 0) return 1;
811 return 0;
812}
813
Martin v. Löwis39195712003-01-04 00:33:13 +0000814PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
815
Martin v. Löwisffad6332002-11-26 09:28:05 +0000816static PyObject*
817get_typename(PyTclObject* obj, void* ignored)
818{
819 return PyString_FromString(obj->value->typePtr->name);
820}
821
Martin v. Löwis39195712003-01-04 00:33:13 +0000822
Martin v. Löwisffad6332002-11-26 09:28:05 +0000823static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000824 {"typename", (getter)get_typename, NULL, get_typename__doc__},
825 {"string", (getter)PyTclObject_string, NULL,
826 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000827 {0},
828};
829
Neal Norwitz227b5332006-03-22 09:28:35 +0000830static PyTypeObject PyTclObject_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000831 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000832 "_tkinter.Tcl_Obj", /*tp_name*/
833 sizeof(PyTclObject), /*tp_basicsize*/
834 0, /*tp_itemsize*/
835 /* methods */
836 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
837 0, /*tp_print*/
838 0, /*tp_getattr*/
839 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000840 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000841 (reprfunc)PyTclObject_repr, /*tp_repr*/
842 0, /*tp_as_number*/
843 0, /*tp_as_sequence*/
844 0, /*tp_as_mapping*/
845 0, /*tp_hash*/
846 0, /*tp_call*/
847 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000848 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000849 0, /*tp_setattro*/
850 0, /*tp_as_buffer*/
851 Py_TPFLAGS_DEFAULT, /*tp_flags*/
852 0, /*tp_doc*/
853 0, /*tp_traverse*/
854 0, /*tp_clear*/
855 0, /*tp_richcompare*/
856 0, /*tp_weaklistoffset*/
857 0, /*tp_iter*/
858 0, /*tp_iternext*/
Walter Dörwald6720d912007-07-12 12:12:25 +0000859 0, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000860 0, /*tp_members*/
861 PyTclObject_getsetlist, /*tp_getset*/
862 0, /*tp_base*/
863 0, /*tp_dict*/
864 0, /*tp_descr_get*/
865 0, /*tp_descr_set*/
866 0, /*tp_dictoffset*/
867 0, /*tp_init*/
868 0, /*tp_alloc*/
869 0, /*tp_new*/
870 0, /*tp_free*/
871 0, /*tp_is_gc*/
872};
873
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000874static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000875AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000876{
877 Tcl_Obj *result;
878
879 if (PyString_Check(value))
880 return Tcl_NewStringObj(PyString_AS_STRING(value),
881 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000882 else if (PyBool_Check(value))
883 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossumddefaf32007-01-14 03:31:43 +0000884 else if (PyInt_CheckExact(value))
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000885 return Tcl_NewLongObj(PyInt_AS_LONG(value));
886 else if (PyFloat_Check(value))
887 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
888 else if (PyTuple_Check(value)) {
889 Tcl_Obj **argv = (Tcl_Obj**)
890 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
891 int i;
892 if(!argv)
893 return 0;
894 for(i=0;i<PyTuple_Size(value);i++)
895 argv[i] = AsObj(PyTuple_GetItem(value,i));
896 result = Tcl_NewListObj(PyTuple_Size(value), argv);
897 ckfree(FREECAST argv);
898 return result;
899 }
900 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000901 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000902 Py_ssize_t size = PyUnicode_GET_SIZE(value);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000903 /* This #ifdef assumes that Tcl uses UCS-2.
904 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000905#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000906 Tcl_UniChar *outbuf;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000907 Py_ssize_t i;
908 assert(size < size * sizeof(Tcl_UniChar));
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000909 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
910 if (!outbuf) {
911 PyErr_NoMemory();
912 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000913 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000914 for (i = 0; i < size; i++) {
915 if (inbuf[i] >= 0x10000) {
916 /* Tcl doesn't do UTF-16, yet. */
917 PyErr_SetString(PyExc_ValueError,
918 "unsupported character");
919 ckfree(FREECAST outbuf);
920 return NULL;
921 }
922 outbuf[i] = inbuf[i];
923 }
924 result = Tcl_NewUnicodeObj(outbuf, size);
925 ckfree(FREECAST outbuf);
926 return result;
927#else
928 return Tcl_NewUnicodeObj(inbuf, size);
929#endif
930
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000931 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000932 else if(PyTclObject_Check(value)) {
933 Tcl_Obj *v = ((PyTclObject*)value)->value;
934 Tcl_IncrRefCount(v);
935 return v;
936 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000937 else {
938 PyObject *v = PyObject_Str(value);
939 if (!v)
940 return 0;
941 result = AsObj(v);
942 Py_DECREF(v);
943 return result;
944 }
945}
946
Martin v. Löwisffad6332002-11-26 09:28:05 +0000947static PyObject*
948FromObj(PyObject* tkapp, Tcl_Obj *value)
949{
950 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000951 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000952
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000953 if (value->typePtr == NULL) {
954 /* If the result contains any bytes with the top bit set,
955 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000956 int i;
957 char *s = value->bytes;
958 int len = value->length;
959 for (i = 0; i < len; i++) {
960 if (value->bytes[i] & 0x80)
961 break;
962 }
963
964 if (i == value->length)
965 result = PyString_FromStringAndSize(s, len);
966 else {
967 /* Convert UTF-8 to Unicode string */
968 result = PyUnicode_DecodeUTF8(s, len, "strict");
969 if (result == NULL) {
970 PyErr_Clear();
971 result = PyString_FromStringAndSize(s, len);
972 }
973 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000974 return result;
975 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000976
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000977 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000978 result = value->internalRep.longValue ? Py_True : Py_False;
979 Py_INCREF(result);
980 return result;
981 }
982
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000983 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000984 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000985 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000986 return PyString_FromStringAndSize(data, size);
987 }
988
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000989 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000990 return PyFloat_FromDouble(value->internalRep.doubleValue);
991 }
992
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000993 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000994 return PyInt_FromLong(value->internalRep.longValue);
995 }
996
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000997 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000998 int size;
999 int i, status;
1000 PyObject *elem;
1001 Tcl_Obj *tcl_elem;
1002
1003 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1004 if (status == TCL_ERROR)
1005 return Tkinter_Error(tkapp);
1006 result = PyTuple_New(size);
1007 if (!result)
1008 return NULL;
1009 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001010 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001011 value, i, &tcl_elem);
1012 if (status == TCL_ERROR) {
1013 Py_DECREF(result);
1014 return Tkinter_Error(tkapp);
1015 }
1016 elem = FromObj(tkapp, tcl_elem);
1017 if (!elem) {
1018 Py_DECREF(result);
1019 return NULL;
1020 }
1021 PyTuple_SetItem(result, i, elem);
1022 }
1023 return result;
1024 }
1025
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001026 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001027 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001028 }
1029
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001030 if (value->typePtr == app->StringType) {
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001031#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001032 PyObject *result;
1033 int size;
1034 Tcl_UniChar *input;
1035 Py_UNICODE *output;
1036
1037 size = Tcl_GetCharLength(value);
1038 result = PyUnicode_FromUnicode(NULL, size);
1039 if (!result)
1040 return NULL;
1041 input = Tcl_GetUnicode(value);
1042 output = PyUnicode_AS_UNICODE(result);
1043 while (size--)
1044 *output++ = *input++;
1045 return result;
1046#else
1047 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1048 Tcl_GetCharLength(value));
1049#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +00001050 }
1051
1052 return newPyTclObject(value);
1053}
1054
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001055/* This mutex synchronizes inter-thread command calls. */
1056
1057TCL_DECLARE_MUTEX(call_mutex)
1058
1059typedef struct Tkapp_CallEvent {
1060 Tcl_Event ev; /* Must be first */
1061 TkappObject *self;
1062 PyObject *args;
1063 int flags;
1064 PyObject **res;
1065 PyObject **exc_type, **exc_value, **exc_tb;
1066 Tcl_Condition done;
1067} Tkapp_CallEvent;
1068
1069void
1070Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001071{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001072 int i;
1073 for (i = 0; i < objc; i++)
1074 Tcl_DecrRefCount(objv[i]);
1075 if (objv != objStore)
1076 ckfree(FREECAST objv);
1077}
Guido van Rossum18468821994-06-20 07:49:28 +00001078
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001079/* Convert Python objects to Tcl objects. This must happen in the
1080 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001081
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001082static Tcl_Obj**
1083Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1084{
1085 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001086 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001087 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001088 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001089
Guido van Rossum212643f1998-04-29 16:22:14 +00001090 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001091 objv[0] = AsObj(args);
1092 if (objv[0] == 0)
1093 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001094 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001095 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001096 }
1097 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001098 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001099
Guido van Rossum632de272000-03-29 00:19:50 +00001100 if (objc > ARGSZ) {
1101 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1102 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001103 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001104 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001105 goto finally;
1106 }
1107 }
1108
Guido van Rossum632de272000-03-29 00:19:50 +00001109 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001110 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001111 if (v == Py_None) {
1112 objc = i;
1113 break;
1114 }
Guido van Rossum632de272000-03-29 00:19:50 +00001115 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001116 if (!objv[i]) {
1117 /* Reset objc, so it attempts to clear
1118 objects only up to i. */
1119 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001120 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001121 }
Guido van Rossum632de272000-03-29 00:19:50 +00001122 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001123 }
1124 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001125 *pobjc = objc;
1126 return objv;
1127finally:
1128 Tkapp_CallDeallocArgs(objv, objStore, objc);
1129 return NULL;
1130}
Guido van Rossum212643f1998-04-29 16:22:14 +00001131
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001132/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001133
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001134static PyObject*
1135Tkapp_CallResult(TkappObject *self)
1136{
1137 PyObject *res = NULL;
1138 if(self->wantobjects) {
1139 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001140 /* Not sure whether the IncrRef is necessary, but something
1141 may overwrite the interpreter result while we are
1142 converting it. */
1143 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001144 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001145 Tcl_DecrRefCount(value);
1146 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001147 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001148 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001149
Guido van Rossum990f5c62000-05-04 15:07:16 +00001150 /* If the result contains any bytes with the top bit set,
1151 it's UTF-8 and we should decode it to Unicode */
1152 while (*p != '\0') {
1153 if (*p & 0x80)
1154 break;
1155 p++;
1156 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001157
Guido van Rossum990f5c62000-05-04 15:07:16 +00001158 if (*p == '\0')
1159 res = PyString_FromStringAndSize(s, (int)(p-s));
1160 else {
1161 /* Convert UTF-8 to Unicode string */
1162 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001163 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1164 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001165 PyErr_Clear();
1166 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001167 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001168 }
1169 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001170 return res;
1171}
Guido van Rossum632de272000-03-29 00:19:50 +00001172
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001173/* Tkapp_CallProc is the event procedure that is executed in the context of
1174 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1175 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001176
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001177static int
1178Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1179{
1180 Tcl_Obj *objStore[ARGSZ];
1181 Tcl_Obj **objv;
1182 int objc;
1183 int i;
1184 ENTER_PYTHON
1185 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1186 if (!objv) {
1187 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1188 *(e->res) = NULL;
1189 }
1190 LEAVE_PYTHON
1191 if (!objv)
1192 goto done;
1193 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1194 ENTER_PYTHON
1195 if (i == TCL_ERROR) {
1196 *(e->res) = NULL;
1197 *(e->exc_type) = NULL;
1198 *(e->exc_tb) = NULL;
1199 *(e->exc_value) = PyObject_CallFunction(
1200 Tkinter_TclError, "s",
1201 Tcl_GetStringResult(e->self->interp));
1202 }
1203 else {
1204 *(e->res) = Tkapp_CallResult(e->self);
1205 }
1206 LEAVE_PYTHON
1207 done:
1208 /* Wake up calling thread. */
1209 Tcl_MutexLock(&call_mutex);
1210 Tcl_ConditionNotify(&e->done);
1211 Tcl_MutexUnlock(&call_mutex);
1212 return 1;
1213}
1214
1215/* This is the main entry point for calling a Tcl command.
1216 It supports three cases, with regard to threading:
1217 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1218 the context of the calling thread.
1219 2. Tcl is threaded, caller of the command is in the interpreter thread:
1220 Execute the command in the calling thread. Since the Tcl lock will
1221 not be used, we can merge that with case 1.
1222 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1223 the interpreter thread. Allocation of Tcl objects needs to occur in the
1224 interpreter thread, so we ship the PyObject* args to the target thread,
1225 and perform processing there. */
1226
1227static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001228Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001229{
1230 Tcl_Obj *objStore[ARGSZ];
1231 Tcl_Obj **objv = NULL;
1232 int objc, i;
1233 PyObject *res = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001234 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001235 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1236 int flags = TCL_EVAL_DIRECT;
1237
Guido van Rossum992d4a32007-07-11 13:09:30 +00001238 /* If args is a single tuple, replace with contents of tuple */
1239 if (1 == PyTuple_Size(args)){
1240 PyObject* item = PyTuple_GetItem(args, 0);
1241 if (PyTuple_Check(item))
1242 args = item;
1243 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001244#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001245 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1246 /* We cannot call the command directly. Instead, we must
1247 marshal the parameters to the interpreter thread. */
1248 Tkapp_CallEvent *ev;
1249 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001250 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001251 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001252 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1253 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1254 ev->self = self;
1255 ev->args = args;
1256 ev->res = &res;
1257 ev->exc_type = &exc_type;
1258 ev->exc_value = &exc_value;
1259 ev->exc_tb = &exc_tb;
1260 ev->done = (Tcl_Condition)0;
1261
1262 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1263
1264 if (res == NULL) {
1265 if (exc_type)
1266 PyErr_Restore(exc_type, exc_value, exc_tb);
1267 else
1268 PyErr_SetObject(Tkinter_TclError, exc_value);
1269 }
1270 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001271 else
1272#endif
1273 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001274
1275 objv = Tkapp_CallArgs(args, objStore, &objc);
1276 if (!objv)
1277 return NULL;
1278
1279 ENTER_TCL
1280
1281 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1282
1283 ENTER_OVERLAP
1284
1285 if (i == TCL_ERROR)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001286 Tkinter_Error(selfptr);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001287 else
1288 res = Tkapp_CallResult(self);
1289
1290 LEAVE_OVERLAP_TCL
1291
1292 Tkapp_CallDeallocArgs(objv, objStore, objc);
1293 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001294 return res;
1295}
1296
1297
1298static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001299Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001300{
Guido van Rossum212643f1998-04-29 16:22:14 +00001301 /* Could do the same here as for Tkapp_Call(), but this is not used
1302 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1303 way for the user to do what all its Global* variants do (save and
1304 reset the scope pointer, call the local version, restore the saved
1305 scope pointer). */
1306
Guido van Rossum62320c91998-06-15 04:36:09 +00001307 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001308 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001309
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001310 CHECK_TCL_APPARTMENT;
1311
Guido van Rossum62320c91998-06-15 04:36:09 +00001312 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001313 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001314 int err;
1315 ENTER_TCL
1316 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001317 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001318 if (err == TCL_ERROR)
1319 res = Tkinter_Error(self);
1320 else
1321 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001322 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001323 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001324 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001325
1326 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001327}
1328
1329static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001330Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001331{
Barry Warsawfa701a81997-01-16 00:15:11 +00001332 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001333 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001334 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001335
Guido van Rossum43713e52000-02-29 13:59:29 +00001336 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001337 return NULL;
1338
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001339 CHECK_TCL_APPARTMENT;
1340
Guido van Rossum00d93061998-05-28 23:06:38 +00001341 ENTER_TCL
1342 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001343 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001344 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001345 res = Tkinter_Error(self);
1346 else
1347 res = PyString_FromString(Tkapp_Result(self));
1348 LEAVE_OVERLAP_TCL
1349 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001350}
1351
1352static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001353Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001354{
Barry Warsawfa701a81997-01-16 00:15:11 +00001355 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001356 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001357 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001358
Guido van Rossum43713e52000-02-29 13:59:29 +00001359 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001360 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001361
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001362 CHECK_TCL_APPARTMENT;
1363
Guido van Rossum00d93061998-05-28 23:06:38 +00001364 ENTER_TCL
1365 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001366 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001367 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001368 res = Tkinter_Error(self);
1369 else
1370 res = PyString_FromString(Tkapp_Result(self));
1371 LEAVE_OVERLAP_TCL
1372 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001373}
1374
1375static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001376Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001377{
Barry Warsawfa701a81997-01-16 00:15:11 +00001378 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001379 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001380 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001381
Guido van Rossum43713e52000-02-29 13:59:29 +00001382 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001383 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001384
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001385 CHECK_TCL_APPARTMENT;
1386
Guido van Rossum00d93061998-05-28 23:06:38 +00001387 ENTER_TCL
1388 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001389 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001390 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001391 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001392
Guido van Rossum62320c91998-06-15 04:36:09 +00001393 else
1394 res = PyString_FromString(Tkapp_Result(self));
1395 LEAVE_OVERLAP_TCL
1396 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001397}
1398
1399static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001400Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001401{
Barry Warsawfa701a81997-01-16 00:15:11 +00001402 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001403 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001404 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001405
Guido van Rossum35d43371997-08-02 00:09:09 +00001406 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001407 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001408
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001409 CHECK_TCL_APPARTMENT;
1410
Guido van Rossum00d93061998-05-28 23:06:38 +00001411 ENTER_TCL
1412 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001413 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001414 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001415 res = Tkinter_Error(self);
1416 else
1417 res = PyString_FromString(Tkapp_Result(self));
1418 LEAVE_OVERLAP_TCL
1419 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001420}
1421
1422static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001423Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001424{
Barry Warsawfa701a81997-01-16 00:15:11 +00001425 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001426
Guido van Rossum43713e52000-02-29 13:59:29 +00001427 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001428 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001429 CHECK_TCL_APPARTMENT;
1430
Guido van Rossum00d93061998-05-28 23:06:38 +00001431 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001432 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001433 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001434
Barry Warsawfa701a81997-01-16 00:15:11 +00001435 Py_INCREF(Py_None);
1436 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001437}
1438
Barry Warsawfa701a81997-01-16 00:15:11 +00001439
1440
Guido van Rossum18468821994-06-20 07:49:28 +00001441/** Tcl Variable **/
1442
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001443TCL_DECLARE_MUTEX(var_mutex)
1444
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001445typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001446typedef struct VarEvent {
1447 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001448 PyObject *self;
1449 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001450 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001451 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001452 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001453 PyObject **exc_type;
1454 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001455 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001456} VarEvent;
1457
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001458static int
1459varname_converter(PyObject *in, void *_out)
1460{
1461 char **out = (char**)_out;
1462 if (PyString_Check(in)) {
1463 *out = PyString_AsString(in);
1464 return 1;
1465 }
Guido van Rossumf761e102007-07-23 18:34:37 +00001466 if (PyUnicode_Check(in)) {
1467 *out = PyUnicode_AsString(in);
1468 return 1;
1469 }
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001470 if (PyTclObject_Check(in)) {
1471 *out = PyTclObject_TclString(in);
1472 return 1;
1473 }
1474 /* XXX: Should give diagnostics. */
1475 return 0;
1476}
1477
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001478void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001479var_perform(VarEvent *ev)
1480{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001481 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1482 if (!*(ev->res)) {
1483 PyObject *exc, *val, *tb;
1484 PyErr_Fetch(&exc, &val, &tb);
1485 PyErr_NormalizeException(&exc, &val, &tb);
1486 *(ev->exc_type) = exc;
1487 *(ev->exc_val) = val;
1488 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001489 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001490
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001491}
1492
1493static int
1494var_proc(VarEvent* ev, int flags)
1495{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001496 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001497 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001498 Tcl_MutexLock(&var_mutex);
1499 Tcl_ConditionNotify(&ev->cond);
1500 Tcl_MutexUnlock(&var_mutex);
1501 LEAVE_PYTHON
1502 return 1;
1503}
1504
1505static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001506var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001507{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001508 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001509#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001510 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001511 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001512 VarEvent *ev;
1513 PyObject *res, *exc_type, *exc_val;
1514
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001515 /* The current thread is not the interpreter thread. Marshal
1516 the call to the interpreter thread, then wait for
1517 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001518 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001519 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001520
1521 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1522
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001523 ev->self = selfptr;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001524 ev->args = args;
1525 ev->flags = flags;
1526 ev->func = func;
1527 ev->res = &res;
1528 ev->exc_type = &exc_type;
1529 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001530 ev->cond = NULL;
1531 ev->ev.proc = (Tcl_EventProc*)var_proc;
1532 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001533 if (!res) {
1534 PyErr_SetObject(exc_type, exc_val);
1535 Py_DECREF(exc_type);
1536 Py_DECREF(exc_val);
1537 return NULL;
1538 }
1539 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001540 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001541#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001542 /* Tcl is not threaded, or this is the interpreter thread. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001543 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001544}
1545
Guido van Rossum18468821994-06-20 07:49:28 +00001546static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001547SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001548{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001549 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001550 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001551 PyObject *res = NULL;
1552 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001553
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001554 if (PyArg_ParseTuple(args, "O&O:setvar",
1555 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001556 /* XXX Acquire tcl lock??? */
1557 newval = AsObj(newValue);
1558 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001559 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001560 ENTER_TCL
1561 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1562 newval, flags);
1563 ENTER_OVERLAP
1564 if (!ok)
1565 Tkinter_Error(self);
1566 else {
1567 res = Py_None;
1568 Py_INCREF(res);
1569 }
1570 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001571 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001572 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001573 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001574 if (PyArg_ParseTuple(args, "ssO:setvar",
1575 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001576 /* XXX must hold tcl lock already??? */
1577 newval = AsObj(newValue);
1578 ENTER_TCL
1579 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1580 ENTER_OVERLAP
1581 if (!ok)
1582 Tkinter_Error(self);
1583 else {
1584 res = Py_None;
1585 Py_INCREF(res);
1586 }
1587 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001588 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001589 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001590 return NULL;
1591 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001592 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001593 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001594}
1595
1596static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001597Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001598{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001599 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001600}
1601
1602static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001603Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001604{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001605 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001606}
1607
Barry Warsawfa701a81997-01-16 00:15:11 +00001608
1609
Guido van Rossum18468821994-06-20 07:49:28 +00001610static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001611GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001612{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001613 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001614 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001615 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001616
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001617 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1618 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001619 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001620
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001621 ENTER_TCL
1622 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1623 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001624 if (tres == NULL) {
1625 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1626 } else {
1627 if (((TkappObject*)self)->wantobjects) {
1628 res = FromObj(self, tres);
1629 }
1630 else {
1631 res = PyString_FromString(Tcl_GetString(tres));
1632 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001633 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001634 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001635 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001636}
1637
1638static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001639Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001640{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001641 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001642}
1643
1644static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001645Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001646{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001647 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001648}
1649
Barry Warsawfa701a81997-01-16 00:15:11 +00001650
1651
Guido van Rossum18468821994-06-20 07:49:28 +00001652static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001653UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001654{
Guido van Rossum35d43371997-08-02 00:09:09 +00001655 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001656 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001657 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001658
Guido van Rossum43713e52000-02-29 13:59:29 +00001659 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001660 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001661
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001662 ENTER_TCL
1663 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1664 ENTER_OVERLAP
1665 if (code == TCL_ERROR)
1666 res = Tkinter_Error(self);
1667 else {
1668 Py_INCREF(Py_None);
1669 res = Py_None;
1670 }
1671 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001672 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001673}
1674
1675static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001676Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001677{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001678 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001679}
1680
1681static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001682Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001683{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001684 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001685}
1686
Barry Warsawfa701a81997-01-16 00:15:11 +00001687
1688
Guido van Rossum18468821994-06-20 07:49:28 +00001689/** Tcl to Python **/
1690
1691static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001692Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001693{
Barry Warsawfa701a81997-01-16 00:15:11 +00001694 char *s;
1695 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001696
Martin v. Löwisffad6332002-11-26 09:28:05 +00001697 if (PyTuple_Size(args) == 1) {
1698 PyObject* o = PyTuple_GetItem(args, 0);
1699 if (PyInt_Check(o)) {
1700 Py_INCREF(o);
1701 return o;
1702 }
1703 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001704 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001705 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001706 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001707 return Tkinter_Error(self);
1708 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001709}
1710
1711static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001712Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001713{
Barry Warsawfa701a81997-01-16 00:15:11 +00001714 char *s;
1715 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001716
Martin v. Löwisffad6332002-11-26 09:28:05 +00001717 if (PyTuple_Size(args) == 1) {
1718 PyObject *o = PyTuple_GetItem(args, 0);
1719 if (PyFloat_Check(o)) {
1720 Py_INCREF(o);
1721 return o;
1722 }
1723 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001724 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001725 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001726 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001727 return Tkinter_Error(self);
1728 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001729}
1730
1731static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001732Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001733{
Barry Warsawfa701a81997-01-16 00:15:11 +00001734 char *s;
1735 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001736
Martin v. Löwisffad6332002-11-26 09:28:05 +00001737 if (PyTuple_Size(args) == 1) {
1738 PyObject *o = PyTuple_GetItem(args, 0);
1739 if (PyInt_Check(o)) {
1740 Py_INCREF(o);
1741 return o;
1742 }
1743 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001744 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001745 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001746 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1747 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001748 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001749}
1750
1751static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001752Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001753{
Barry Warsawfa701a81997-01-16 00:15:11 +00001754 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001755 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001756 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001757
Guido van Rossum43713e52000-02-29 13:59:29 +00001758 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001759 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001760
1761 CHECK_TCL_APPARTMENT;
1762
Guido van Rossum00d93061998-05-28 23:06:38 +00001763 ENTER_TCL
1764 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001765 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001766 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001767 res = Tkinter_Error(self);
1768 else
1769 res = Py_BuildValue("s", Tkapp_Result(self));
1770 LEAVE_OVERLAP_TCL
1771 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001772}
1773
1774static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001775Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001776{
Barry Warsawfa701a81997-01-16 00:15:11 +00001777 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001778 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001779 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001780 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001781
Guido van Rossum43713e52000-02-29 13:59:29 +00001782 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001783 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001784
1785 CHECK_TCL_APPARTMENT;
1786
Guido van Rossum00d93061998-05-28 23:06:38 +00001787 ENTER_TCL
1788 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001789 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001790 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001791 res = Tkinter_Error(self);
1792 else
1793 res = Py_BuildValue("l", v);
1794 LEAVE_OVERLAP_TCL
1795 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001796}
1797
1798static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001799Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001800{
Barry Warsawfa701a81997-01-16 00:15:11 +00001801 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001802 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001803 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001804 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001805
Guido van Rossum43713e52000-02-29 13:59:29 +00001806 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001807 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001808 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001809 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001810 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001811 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001812 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001813 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001814 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001815 res = Tkinter_Error(self);
1816 else
1817 res = Py_BuildValue("d", v);
1818 LEAVE_OVERLAP_TCL
1819 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001820}
1821
1822static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001823Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001824{
Barry Warsawfa701a81997-01-16 00:15:11 +00001825 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001826 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001827 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001828 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001829
Guido van Rossum43713e52000-02-29 13:59:29 +00001830 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001831 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001832 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001833 ENTER_TCL
1834 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001835 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001836 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001837 res = Tkinter_Error(self);
1838 else
1839 res = Py_BuildValue("i", v);
1840 LEAVE_OVERLAP_TCL
1841 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001842}
1843
Barry Warsawfa701a81997-01-16 00:15:11 +00001844
1845
Guido van Rossum18468821994-06-20 07:49:28 +00001846static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001847Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001848{
Barry Warsawfa701a81997-01-16 00:15:11 +00001849 char *list;
1850 int argc;
1851 char **argv;
1852 PyObject *v;
1853 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001854
Martin v. Löwisffad6332002-11-26 09:28:05 +00001855 if (PyTuple_Size(args) == 1) {
1856 v = PyTuple_GetItem(args, 0);
1857 if (PyTuple_Check(v)) {
1858 Py_INCREF(v);
1859 return v;
1860 }
1861 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001862 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001863 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001864
Neal Norwitzd1c55102003-05-29 00:17:03 +00001865 if (Tcl_SplitList(Tkapp_Interp(self), list,
1866 &argc, &argv) == TCL_ERROR) {
1867 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001868 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001869 }
Guido van Rossum18468821994-06-20 07:49:28 +00001870
Barry Warsawfa701a81997-01-16 00:15:11 +00001871 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001872 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001873
Barry Warsawfa701a81997-01-16 00:15:11 +00001874 for (i = 0; i < argc; i++) {
1875 PyObject *s = PyString_FromString(argv[i]);
1876 if (!s || PyTuple_SetItem(v, i, s)) {
1877 Py_DECREF(v);
1878 v = NULL;
1879 goto finally;
1880 }
1881 }
Guido van Rossum18468821994-06-20 07:49:28 +00001882
Barry Warsawfa701a81997-01-16 00:15:11 +00001883 finally:
1884 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001885 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001886 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001887}
1888
1889static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001890Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001891{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001892 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001893 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001894
Martin v. Löwisffad6332002-11-26 09:28:05 +00001895 if (PyTuple_Size(args) == 1) {
1896 PyObject* o = PyTuple_GetItem(args, 0);
1897 if (PyTuple_Check(o)) {
1898 o = SplitObj(o);
1899 return o;
1900 }
1901 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001902 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001903 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001904 v = Split(list);
1905 PyMem_Free(list);
1906 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001907}
1908
1909static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001910Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001911{
Barry Warsawfa701a81997-01-16 00:15:11 +00001912 char *s = Merge(args);
1913 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001914
Barry Warsawfa701a81997-01-16 00:15:11 +00001915 if (s) {
1916 res = PyString_FromString(s);
1917 ckfree(s);
1918 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001919
1920 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001921}
1922
Barry Warsawfa701a81997-01-16 00:15:11 +00001923
1924
Guido van Rossum18468821994-06-20 07:49:28 +00001925/** Tcl Command **/
1926
Guido van Rossum00d93061998-05-28 23:06:38 +00001927/* Client data struct */
1928typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001929 PyObject *self;
1930 PyObject *func;
1931} PythonCmd_ClientData;
1932
1933static int
Fred Drake509d79a2000-07-08 04:04:38 +00001934PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001935{
1936 errorInCmd = 1;
1937 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1938 LEAVE_PYTHON
1939 return TCL_ERROR;
1940}
1941
Guido van Rossum18468821994-06-20 07:49:28 +00001942/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001943 * function or method.
1944 */
Guido van Rossum18468821994-06-20 07:49:28 +00001945static int
Fred Drake509d79a2000-07-08 04:04:38 +00001946PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001947{
Guido van Rossum00d93061998-05-28 23:06:38 +00001948 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Martin v. Löwis50fb8662007-08-13 05:41:41 +00001949 PyObject *self, *func, *arg, *res;
Guido van Rossum2834b972000-10-06 16:58:26 +00001950 int i, rv;
Martin v. Löwis50fb8662007-08-13 05:41:41 +00001951 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001952
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001953 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001954
Barry Warsawfa701a81997-01-16 00:15:11 +00001955 /* TBD: no error checking here since we know, via the
1956 * Tkapp_CreateCommand() that the client data is a two-tuple
1957 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001958 self = data->self;
1959 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001960
Barry Warsawfa701a81997-01-16 00:15:11 +00001961 /* Create argument list (argv1, ..., argvN) */
1962 if (!(arg = PyTuple_New(argc - 1)))
1963 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001964
Barry Warsawfa701a81997-01-16 00:15:11 +00001965 for (i = 0; i < (argc - 1); i++) {
1966 PyObject *s = PyString_FromString(argv[i + 1]);
1967 if (!s || PyTuple_SetItem(arg, i, s)) {
1968 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001969 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001970 }
1971 }
1972 res = PyEval_CallObject(func, arg);
1973 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001974
Barry Warsawfa701a81997-01-16 00:15:11 +00001975 if (res == NULL)
1976 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001977
Martin v. Löwis50fb8662007-08-13 05:41:41 +00001978 tres = AsObj(res);
1979 if (tres == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001980 Py_DECREF(res);
1981 return PythonCmd_Error(interp);
1982 }
Guido van Rossum2834b972000-10-06 16:58:26 +00001983 else {
Martin v. Löwis50fb8662007-08-13 05:41:41 +00001984 Tcl_SetObjResult(Tkapp_Interp(self), tres);
Guido van Rossum2834b972000-10-06 16:58:26 +00001985 rv = TCL_OK;
1986 }
1987
Barry Warsawfa701a81997-01-16 00:15:11 +00001988 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001989
Guido van Rossum00d93061998-05-28 23:06:38 +00001990 LEAVE_PYTHON
1991
Guido van Rossum2834b972000-10-06 16:58:26 +00001992 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001993}
1994
1995static void
Fred Drake509d79a2000-07-08 04:04:38 +00001996PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001997{
Guido van Rossum00d93061998-05-28 23:06:38 +00001998 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1999
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002000 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002001 Py_XDECREF(data->self);
2002 Py_XDECREF(data->func);
2003 PyMem_DEL(data);
2004 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002005}
2006
Barry Warsawfa701a81997-01-16 00:15:11 +00002007
2008
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002009
2010TCL_DECLARE_MUTEX(command_mutex)
2011
2012typedef struct CommandEvent{
2013 Tcl_Event ev;
2014 Tcl_Interp* interp;
2015 char *name;
2016 int create;
2017 int *status;
2018 ClientData *data;
2019 Tcl_Condition done;
2020} CommandEvent;
2021
2022static int
2023Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002024{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002025 if (ev->create)
2026 *ev->status = Tcl_CreateCommand(
2027 ev->interp, ev->name, PythonCmd,
2028 ev->data, PythonCmdDelete) == NULL;
2029 else
2030 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2031 Tcl_MutexLock(&command_mutex);
2032 Tcl_ConditionNotify(&ev->done);
2033 Tcl_MutexUnlock(&command_mutex);
2034 return 1;
2035}
2036
2037static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002038Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002039{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002040 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002041 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002042 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002043 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002044 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002045
Guido van Rossum43713e52000-02-29 13:59:29 +00002046 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002047 return NULL;
2048 if (!PyCallable_Check(func)) {
2049 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002050 return NULL;
2051 }
Guido van Rossum18468821994-06-20 07:49:28 +00002052
Martin v. Löwisa9656492003-03-30 08:44:58 +00002053#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002054 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002055 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002056 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002057#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002058
Guido van Rossum00d93061998-05-28 23:06:38 +00002059 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002060 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002061 return PyErr_NoMemory();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002062 Py_INCREF(self);
2063 Py_INCREF(func);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002064 data->self = selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002065 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002066
2067 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2068 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2069 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2070 ev->interp = self->interp;
2071 ev->create = 1;
2072 ev->name = cmdName;
2073 ev->data = (ClientData)data;
2074 ev->status = &err;
2075 ev->done = NULL;
2076 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2077 }
2078 else {
2079 ENTER_TCL
2080 err = Tcl_CreateCommand(
2081 Tkapp_Interp(self), cmdName, PythonCmd,
2082 (ClientData)data, PythonCmdDelete) == NULL;
2083 LEAVE_TCL
2084 }
2085 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002086 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002087 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002088 return NULL;
2089 }
Guido van Rossum18468821994-06-20 07:49:28 +00002090
Barry Warsawfa701a81997-01-16 00:15:11 +00002091 Py_INCREF(Py_None);
2092 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002093}
2094
Barry Warsawfa701a81997-01-16 00:15:11 +00002095
2096
Guido van Rossum18468821994-06-20 07:49:28 +00002097static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002098Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002099{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002100 TkappObject *self = (TkappObject*)selfptr;
Barry Warsawfa701a81997-01-16 00:15:11 +00002101 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002102 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002103
Guido van Rossum43713e52000-02-29 13:59:29 +00002104 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002105 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002106 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2107 CommandEvent *ev;
2108 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2109 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2110 ev->interp = self->interp;
2111 ev->create = 0;
2112 ev->name = cmdName;
2113 ev->status = &err;
2114 ev->done = NULL;
2115 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2116 &command_mutex);
2117 }
2118 else {
2119 ENTER_TCL
2120 err = Tcl_DeleteCommand(self->interp, cmdName);
2121 LEAVE_TCL
2122 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002123 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002124 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2125 return NULL;
2126 }
2127 Py_INCREF(Py_None);
2128 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002129}
2130
Barry Warsawfa701a81997-01-16 00:15:11 +00002131
2132
Guido van Rossum00d93061998-05-28 23:06:38 +00002133#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002134/** File Handler **/
2135
Guido van Rossum00d93061998-05-28 23:06:38 +00002136typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002137 PyObject *func;
2138 PyObject *file;
2139 int id;
2140 struct _fhcdata *next;
2141} FileHandler_ClientData;
2142
2143static FileHandler_ClientData *HeadFHCD;
2144
2145static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002146NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002147{
2148 FileHandler_ClientData *p;
2149 p = PyMem_NEW(FileHandler_ClientData, 1);
2150 if (p != NULL) {
2151 Py_XINCREF(func);
2152 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002153 p->func = func;
2154 p->file = file;
2155 p->id = id;
2156 p->next = HeadFHCD;
2157 HeadFHCD = p;
2158 }
2159 return p;
2160}
2161
2162static void
Fred Drake509d79a2000-07-08 04:04:38 +00002163DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002164{
2165 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002166
2167 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002168 while ((p = *pp) != NULL) {
2169 if (p->id == id) {
2170 *pp = p->next;
2171 Py_XDECREF(p->func);
2172 Py_XDECREF(p->file);
2173 PyMem_DEL(p);
2174 }
2175 else
2176 pp = &p->next;
2177 }
2178}
2179
Guido van Rossuma597dde1995-01-10 20:56:29 +00002180static void
Fred Drake509d79a2000-07-08 04:04:38 +00002181FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002182{
Guido van Rossum00d93061998-05-28 23:06:38 +00002183 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002184 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002185
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002186 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002187 func = data->func;
2188 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002189
Barry Warsawfa701a81997-01-16 00:15:11 +00002190 arg = Py_BuildValue("(Oi)", file, (long) mask);
2191 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002192 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002193
2194 if (res == NULL) {
2195 errorInCmd = 1;
2196 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2197 }
2198 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002199 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002200}
2201
Guido van Rossum18468821994-06-20 07:49:28 +00002202static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002203Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2204 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002205{
Guido van Rossum00d93061998-05-28 23:06:38 +00002206 FileHandler_ClientData *data;
2207 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002208 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002209
Guido van Rossum2834b972000-10-06 16:58:26 +00002210 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2211 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002212 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002213
Martin v. Löwisa9656492003-03-30 08:44:58 +00002214#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002215 if (!self && !tcl_lock) {
2216 /* We don't have the Tcl lock since Tcl is threaded. */
2217 PyErr_SetString(PyExc_RuntimeError,
2218 "_tkinter.createfilehandler not supported "
2219 "for threaded Tcl");
2220 return NULL;
2221 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002222#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002223
2224 if (self) {
2225 CHECK_TCL_APPARTMENT;
2226 }
2227
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002228 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002229 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002230 return NULL;
2231 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002232 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002233 return NULL;
2234 }
2235
Guido van Rossuma80649b2000-03-28 20:07:05 +00002236 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002237 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002238 return NULL;
2239
Barry Warsawfa701a81997-01-16 00:15:11 +00002240 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002241 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002242 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002243 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002244 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002245 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002246}
2247
2248static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002249Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002250{
Barry Warsawfa701a81997-01-16 00:15:11 +00002251 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002252 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002253
Guido van Rossum43713e52000-02-29 13:59:29 +00002254 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002255 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002256
Martin v. Löwisa9656492003-03-30 08:44:58 +00002257#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002258 if (!self && !tcl_lock) {
2259 /* We don't have the Tcl lock since Tcl is threaded. */
2260 PyErr_SetString(PyExc_RuntimeError,
2261 "_tkinter.deletefilehandler not supported "
2262 "for threaded Tcl");
2263 return NULL;
2264 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002265#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002266
2267 if (self) {
2268 CHECK_TCL_APPARTMENT;
2269 }
2270
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002271 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002272 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002273 return NULL;
2274
Guido van Rossuma80649b2000-03-28 20:07:05 +00002275 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002276
Barry Warsawfa701a81997-01-16 00:15:11 +00002277 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002278 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002279 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002280 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002281 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002282 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002283}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002284#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002285
Barry Warsawfa701a81997-01-16 00:15:11 +00002286
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002287/**** Tktt Object (timer token) ****/
2288
Jeremy Hylton938ace62002-07-17 16:30:39 +00002289static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002290
Guido van Rossum00d93061998-05-28 23:06:38 +00002291typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002292 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002293 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002294 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002295} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002296
2297static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002298Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002299{
Barry Warsawfa701a81997-01-16 00:15:11 +00002300 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002301 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002302
Guido van Rossum43713e52000-02-29 13:59:29 +00002303 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002304 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002305 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002306 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002307 v->token = NULL;
2308 }
2309 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002310 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002311 Py_DECREF(func);
2312 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002313 }
2314 Py_INCREF(Py_None);
2315 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002316}
2317
2318static PyMethodDef Tktt_methods[] =
2319{
Neal Norwitzb0493252002-03-31 14:44:22 +00002320 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002321 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002322};
2323
2324static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002325Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002326{
Barry Warsawfa701a81997-01-16 00:15:11 +00002327 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002328
Guido van Rossumb18618d2000-05-03 23:44:39 +00002329 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002330 if (v == NULL)
2331 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002332
Guido van Rossum00d93061998-05-28 23:06:38 +00002333 Py_INCREF(func);
2334 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002335 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002336
2337 /* Extra reference, deleted when called or when handler is deleted */
2338 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002339 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002340}
2341
2342static void
Fred Drake509d79a2000-07-08 04:04:38 +00002343Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002344{
Guido van Rossum00d93061998-05-28 23:06:38 +00002345 TkttObject *v = (TkttObject *)self;
2346 PyObject *func = v->func;
2347
2348 Py_XDECREF(func);
2349
Guido van Rossumb18618d2000-05-03 23:44:39 +00002350 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002351}
2352
Guido van Rossum597ac201998-05-12 14:36:19 +00002353static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002354Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002355{
Barry Warsawfa701a81997-01-16 00:15:11 +00002356 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002357 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002358
Tim Peters885d4572001-11-28 20:27:42 +00002359 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002360 v->func == NULL ? ", handler deleted" : "");
Walter Dörwald1ab83302007-05-18 17:15:44 +00002361 return PyUnicode_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002362}
2363
2364static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002365Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002366{
Barry Warsawfa701a81997-01-16 00:15:11 +00002367 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002368}
2369
2370static PyTypeObject Tktt_Type =
2371{
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00002372 PyVarObject_HEAD_INIT(NULL, 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002373 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002374 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002375 0, /*tp_itemsize */
2376 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002377 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002378 Tktt_GetAttr, /*tp_getattr */
2379 0, /*tp_setattr */
2380 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002381 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002382 0, /*tp_as_number */
2383 0, /*tp_as_sequence */
2384 0, /*tp_as_mapping */
2385 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002386};
2387
Barry Warsawfa701a81997-01-16 00:15:11 +00002388
2389
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002390/** Timer Handler **/
2391
2392static void
Fred Drake509d79a2000-07-08 04:04:38 +00002393TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002394{
Guido van Rossum00d93061998-05-28 23:06:38 +00002395 TkttObject *v = (TkttObject *)clientData;
2396 PyObject *func = v->func;
2397 PyObject *res;
2398
2399 if (func == NULL)
2400 return;
2401
2402 v->func = NULL;
2403
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002404 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002405
2406 res = PyEval_CallObject(func, NULL);
2407 Py_DECREF(func);
2408 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002409
Barry Warsawfa701a81997-01-16 00:15:11 +00002410 if (res == NULL) {
2411 errorInCmd = 1;
2412 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2413 }
2414 else
2415 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002416
2417 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002418}
2419
2420static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002421Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002422{
Barry Warsawfa701a81997-01-16 00:15:11 +00002423 int milliseconds;
2424 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002425 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002426
Guido van Rossum2834b972000-10-06 16:58:26 +00002427 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2428 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002429 return NULL;
2430 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002431 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002432 return NULL;
2433 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002434
Martin v. Löwisa9656492003-03-30 08:44:58 +00002435#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002436 if (!self && !tcl_lock) {
2437 /* We don't have the Tcl lock since Tcl is threaded. */
2438 PyErr_SetString(PyExc_RuntimeError,
2439 "_tkinter.createtimerhandler not supported "
2440 "for threaded Tcl");
2441 return NULL;
2442 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002443#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002444
2445 if (self) {
2446 CHECK_TCL_APPARTMENT;
2447 }
2448
Guido van Rossum00d93061998-05-28 23:06:38 +00002449 v = Tktt_New(func);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002450 if (v) {
2451 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2452 (ClientData)v);
2453 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002454
Guido van Rossum00d93061998-05-28 23:06:38 +00002455 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002456}
2457
Barry Warsawfa701a81997-01-16 00:15:11 +00002458
Guido van Rossum18468821994-06-20 07:49:28 +00002459/** Event Loop **/
2460
Guido van Rossum18468821994-06-20 07:49:28 +00002461static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002462Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002463{
Barry Warsawfa701a81997-01-16 00:15:11 +00002464 int threshold = 0;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002465 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002466#ifdef WITH_THREAD
2467 PyThreadState *tstate = PyThreadState_Get();
2468#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002469
Guido van Rossum43713e52000-02-29 13:59:29 +00002470 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002471 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002472
Martin v. Löwisa9656492003-03-30 08:44:58 +00002473#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002474 if (!self && !tcl_lock) {
2475 /* We don't have the Tcl lock since Tcl is threaded. */
2476 PyErr_SetString(PyExc_RuntimeError,
2477 "_tkinter.mainloop not supported "
2478 "for threaded Tcl");
2479 return NULL;
2480 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002481#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002482
2483 if (self) {
2484 CHECK_TCL_APPARTMENT;
2485 self->dispatching = 1;
2486 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002487
Barry Warsawfa701a81997-01-16 00:15:11 +00002488 quitMainLoop = 0;
2489 while (Tk_GetNumMainWindows() > threshold &&
2490 !quitMainLoop &&
2491 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002492 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002493 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002494
2495#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002496 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002497 /* Allow other Python threads to run. */
2498 ENTER_TCL
2499 result = Tcl_DoOneEvent(0);
2500 LEAVE_TCL
2501 }
2502 else {
2503 Py_BEGIN_ALLOW_THREADS
2504 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2505 tcl_tstate = tstate;
2506 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2507 tcl_tstate = NULL;
2508 if(tcl_lock)PyThread_release_lock(tcl_lock);
2509 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002510 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002511 Py_END_ALLOW_THREADS
2512 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002513#else
2514 result = Tcl_DoOneEvent(0);
2515#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002516
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002517 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002518 if (self)
2519 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002520 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002521 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002522 if (result < 0)
2523 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002524 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002525 if (self)
2526 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002527 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002528
Barry Warsawfa701a81997-01-16 00:15:11 +00002529 if (errorInCmd) {
2530 errorInCmd = 0;
2531 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2532 excInCmd = valInCmd = trbInCmd = NULL;
2533 return NULL;
2534 }
2535 Py_INCREF(Py_None);
2536 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002537}
2538
2539static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002540Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002541{
Guido van Rossum35d43371997-08-02 00:09:09 +00002542 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002543 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002544
Guido van Rossum43713e52000-02-29 13:59:29 +00002545 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002546 return NULL;
2547
Guido van Rossum00d93061998-05-28 23:06:38 +00002548 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002549 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002550 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002551 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002552}
2553
2554static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002555Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002556{
2557
Guido van Rossum43713e52000-02-29 13:59:29 +00002558 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002559 return NULL;
2560
2561 quitMainLoop = 1;
2562 Py_INCREF(Py_None);
2563 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002564}
2565
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002566static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002567Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002568{
2569
Guido van Rossum43713e52000-02-29 13:59:29 +00002570 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002571 return NULL;
2572
2573 return PyInt_FromLong((long)Tkapp_Interp(self));
2574}
2575
David Aschere2b4b322004-02-18 05:59:53 +00002576static PyObject *
2577Tkapp_TkInit(PyObject *self, PyObject *args)
2578{
Thomas Wouters477c8d52006-05-27 19:21:47 +00002579 static int has_failed;
David Aschere2b4b322004-02-18 05:59:53 +00002580 Tcl_Interp *interp = Tkapp_Interp(self);
Neal Norwitz44dbae82004-02-19 02:44:22 +00002581 Tk_Window main_window;
David Aschere2b4b322004-02-18 05:59:53 +00002582 const char * _tk_exists = NULL;
David Aschere2b4b322004-02-18 05:59:53 +00002583 int err;
Neal Norwitz44dbae82004-02-19 02:44:22 +00002584 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002585
Thomas Wouters477c8d52006-05-27 19:21:47 +00002586 /* In all current versions of Tk (including 8.4.13), Tk_Init
2587 deadlocks on the second call when the first call failed.
2588 To avoid the deadlock, we just refuse the second call through
2589 a static variable. */
2590 if (has_failed) {
2591 PyErr_SetString(Tkinter_TclError,
2592 "Calling Tk_Init again after a previous call failed might deadlock");
2593 return NULL;
2594 }
2595
David Aschere2b4b322004-02-18 05:59:53 +00002596 /* We want to guard against calling Tk_Init() multiple times */
2597 CHECK_TCL_APPARTMENT;
2598 ENTER_TCL
2599 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2600 ENTER_OVERLAP
2601 if (err == TCL_ERROR) {
Thomas Wouters477c8d52006-05-27 19:21:47 +00002602 /* This sets an exception, but we cannot return right
2603 away because we need to exit the overlap first. */
2604 Tkinter_Error(self);
David Aschere2b4b322004-02-18 05:59:53 +00002605 } else {
2606 _tk_exists = Tkapp_Result(self);
2607 }
2608 LEAVE_OVERLAP_TCL
2609 if (err == TCL_ERROR) {
2610 return NULL;
2611 }
2612 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2613 if (Tk_Init(interp) == TCL_ERROR) {
2614 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Thomas Wouters477c8d52006-05-27 19:21:47 +00002615 has_failed = 1;
David Aschere2b4b322004-02-18 05:59:53 +00002616 return NULL;
2617 }
2618 }
2619 Py_INCREF(Py_None);
2620 return Py_None;
2621}
Barry Warsawfa701a81997-01-16 00:15:11 +00002622
Martin v. Löwisffad6332002-11-26 09:28:05 +00002623static PyObject *
2624Tkapp_WantObjects(PyObject *self, PyObject *args)
2625{
2626
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002627 int wantobjects = -1;
2628 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002629 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002630 if (wantobjects == -1)
2631 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002632 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002633
2634 Py_INCREF(Py_None);
2635 return Py_None;
2636}
2637
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002638static PyObject *
2639Tkapp_WillDispatch(PyObject *self, PyObject *args)
2640{
2641
2642 ((TkappObject*)self)->dispatching = 1;
2643
2644 Py_INCREF(Py_None);
2645 return Py_None;
2646}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002647
Barry Warsawfa701a81997-01-16 00:15:11 +00002648
Guido van Rossum18468821994-06-20 07:49:28 +00002649/**** Tkapp Method List ****/
2650
2651static PyMethodDef Tkapp_methods[] =
2652{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002653 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002654 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Guido van Rossumd59da4b2007-05-22 18:11:13 +00002655 {"call", Tkapp_Call, METH_VARARGS},
2656 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002657 {"eval", Tkapp_Eval, METH_VARARGS},
2658 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2659 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2660 {"record", Tkapp_Record, METH_VARARGS},
2661 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2662 {"setvar", Tkapp_SetVar, METH_VARARGS},
2663 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2664 {"getvar", Tkapp_GetVar, METH_VARARGS},
2665 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2666 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2667 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2668 {"getint", Tkapp_GetInt, METH_VARARGS},
2669 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2670 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2671 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2672 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2673 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2674 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2675 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2676 {"split", Tkapp_Split, METH_VARARGS},
Guido van Rossumd59da4b2007-05-22 18:11:13 +00002677 {"merge", Tkapp_Merge, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002678 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2679 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002680#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002681 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2682 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002683#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002684 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2685 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2686 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2687 {"quit", Tkapp_Quit, METH_VARARGS},
2688 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Neal Norwitz44dbae82004-02-19 02:44:22 +00002689 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002690 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002691};
2692
Barry Warsawfa701a81997-01-16 00:15:11 +00002693
2694
Guido van Rossum18468821994-06-20 07:49:28 +00002695/**** Tkapp Type Methods ****/
2696
2697static void
Fred Drake509d79a2000-07-08 04:04:38 +00002698Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002699{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002700 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002701 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002702 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002703 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002704 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002705 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002706}
2707
2708static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002709Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002710{
Guido van Rossum35d43371997-08-02 00:09:09 +00002711 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002712}
2713
2714static PyTypeObject Tkapp_Type =
2715{
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00002716 PyVarObject_HEAD_INIT(NULL, 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002717 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002718 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002719 0, /*tp_itemsize */
2720 Tkapp_Dealloc, /*tp_dealloc */
2721 0, /*tp_print */
2722 Tkapp_GetAttr, /*tp_getattr */
2723 0, /*tp_setattr */
2724 0, /*tp_compare */
2725 0, /*tp_repr */
2726 0, /*tp_as_number */
2727 0, /*tp_as_sequence */
2728 0, /*tp_as_mapping */
2729 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002730};
2731
Barry Warsawfa701a81997-01-16 00:15:11 +00002732
2733
Guido van Rossum18468821994-06-20 07:49:28 +00002734/**** Tkinter Module ****/
2735
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002736typedef struct {
2737 PyObject* tuple;
2738 int size; /* current size */
2739 int maxsize; /* allocated size */
2740} FlattenContext;
2741
2742static int
2743_bump(FlattenContext* context, int size)
2744{
Guido van Rossum2834b972000-10-06 16:58:26 +00002745 /* expand tuple to hold (at least) size new items.
2746 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002747
2748 int maxsize = context->maxsize * 2;
2749
2750 if (maxsize < context->size + size)
2751 maxsize = context->size + size;
2752
2753 context->maxsize = maxsize;
2754
Tim Peters4324aa32001-05-28 22:30:08 +00002755 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002756}
2757
2758static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002759_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002760{
2761 /* add tuple or list to argument tuple (recursively) */
2762
2763 int i, size;
2764
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002765 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002766 PyErr_SetString(PyExc_ValueError,
2767 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002768 return 0;
2769 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002770 size = PyList_GET_SIZE(item);
2771 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002772 if (context->size + size > context->maxsize &&
2773 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002774 return 0;
2775 /* copy items to output tuple */
2776 for (i = 0; i < size; i++) {
2777 PyObject *o = PyList_GET_ITEM(item, i);
2778 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002779 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002780 return 0;
2781 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002782 if (context->size + 1 > context->maxsize &&
2783 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002784 return 0;
2785 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002786 PyTuple_SET_ITEM(context->tuple,
2787 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002788 }
2789 }
2790 } else if (PyTuple_Check(item)) {
2791 /* same, for tuples */
2792 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002793 if (context->size + size > context->maxsize &&
2794 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002795 return 0;
2796 for (i = 0; i < size; i++) {
2797 PyObject *o = PyTuple_GET_ITEM(item, i);
2798 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002799 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002800 return 0;
2801 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002802 if (context->size + 1 > context->maxsize &&
2803 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002804 return 0;
2805 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002806 PyTuple_SET_ITEM(context->tuple,
2807 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002808 }
2809 }
2810 } else {
2811 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2812 return 0;
2813 }
2814 return 1;
2815}
2816
2817static PyObject *
2818Tkinter_Flatten(PyObject* self, PyObject* args)
2819{
2820 FlattenContext context;
2821 PyObject* item;
2822
2823 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2824 return NULL;
2825
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002826 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002827 if (context.maxsize <= 0)
2828 return PyTuple_New(0);
2829
2830 context.tuple = PyTuple_New(context.maxsize);
2831 if (!context.tuple)
2832 return NULL;
2833
2834 context.size = 0;
2835
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002836 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002837 return NULL;
2838
Tim Peters4324aa32001-05-28 22:30:08 +00002839 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002840 return NULL;
2841
2842 return context.tuple;
2843}
2844
Guido van Rossum18468821994-06-20 07:49:28 +00002845static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002846Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002847{
Barry Warsawfa701a81997-01-16 00:15:11 +00002848 char *screenName = NULL;
2849 char *baseName = NULL;
2850 char *className = NULL;
2851 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002852 int wantobjects = 0;
David Aschere2b4b322004-02-18 05:59:53 +00002853 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002854 int sync = 0; /* pass -sync to wish */
2855 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002856
Guido van Rossum35d43371997-08-02 00:09:09 +00002857 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002858 if (baseName != NULL)
2859 baseName++;
2860 else
2861 baseName = Py_GetProgramName();
2862 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002863
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002864 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002865 &screenName, &baseName, &className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002866 &interactive, &wantobjects, &wantTk,
2867 &sync, &use))
Barry Warsawfa701a81997-01-16 00:15:11 +00002868 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002869
Barry Warsawfa701a81997-01-16 00:15:11 +00002870 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002871 interactive, wantobjects, wantTk,
2872 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002873}
2874
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002875static PyObject *
2876Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2877{
2878 int new_val;
2879 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2880 return NULL;
2881 if (new_val < 0) {
2882 PyErr_SetString(PyExc_ValueError,
2883 "busywaitinterval must be >= 0");
2884 return NULL;
2885 }
2886 Tkinter_busywaitinterval = new_val;
2887 Py_INCREF(Py_None);
2888 return Py_None;
2889}
2890
2891static char setbusywaitinterval_doc[] =
2892"setbusywaitinterval(n) -> None\n\
2893\n\
2894Set the busy-wait interval in milliseconds between successive\n\
2895calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2896It should be set to a divisor of the maximum time between\n\
2897frames in an animation.";
2898
2899static PyObject *
2900Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2901{
2902 return PyInt_FromLong(Tkinter_busywaitinterval);
2903}
2904
2905static char getbusywaitinterval_doc[] =
2906"getbusywaitinterval() -> int\n\
2907\n\
2908Return the current busy-wait interval between successive\n\
2909calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2910
Guido van Rossum18468821994-06-20 07:49:28 +00002911static PyMethodDef moduleMethods[] =
2912{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002913 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2914 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002915#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002916 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2917 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002918#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002919 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2920 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2921 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2922 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002923 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2924 setbusywaitinterval_doc},
2925 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2926 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002927 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002928};
2929
Guido van Rossum7bf15641998-05-22 18:28:17 +00002930#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002931
2932static int stdin_ready = 0;
2933
Guido van Rossumad4db171998-06-13 13:56:28 +00002934#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002935static void
Fred Drake509d79a2000-07-08 04:04:38 +00002936MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002937{
2938 stdin_ready = 1;
2939}
Guido van Rossumad4db171998-06-13 13:56:28 +00002940#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002941
Martin v. Löwisa9656492003-03-30 08:44:58 +00002942#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002943static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002944#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002945
Guido van Rossum18468821994-06-20 07:49:28 +00002946static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002947EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002948{
Guido van Rossumad4db171998-06-13 13:56:28 +00002949#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002950 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002951#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002952#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002953 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002954#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002955 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002956 errorInCmd = 0;
2957#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002958 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002959 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002960#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002961 while (!errorInCmd && !stdin_ready) {
2962 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002963#ifdef MS_WINDOWS
2964 if (_kbhit()) {
2965 stdin_ready = 1;
2966 break;
2967 }
2968#endif
2969#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002970 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002971 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002972 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002973
Guido van Rossum00d93061998-05-28 23:06:38 +00002974 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002975
2976 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002977 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002978 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002979 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002980 Py_END_ALLOW_THREADS
2981#else
2982 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002983#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002984
2985 if (result < 0)
2986 break;
2987 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002988#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002989 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002990#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002991 if (errorInCmd) {
2992 errorInCmd = 0;
2993 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2994 excInCmd = valInCmd = trbInCmd = NULL;
2995 PyErr_Print();
2996 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002997#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002998 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002999#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003000 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003001}
Guido van Rossum18468821994-06-20 07:49:28 +00003002
Guido van Rossum00d93061998-05-28 23:06:38 +00003003#endif
3004
Guido van Rossum7bf15641998-05-22 18:28:17 +00003005static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003006EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003007{
Guido van Rossum00d93061998-05-28 23:06:38 +00003008#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003009 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003010#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003011 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003012#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003013 PyOS_InputHook = EventHook;
3014 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003015#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003016}
3017
3018static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003019DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003020{
Guido van Rossum00d93061998-05-28 23:06:38 +00003021#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003022 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3023 PyOS_InputHook = NULL;
3024 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003025#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003026}
3027
Barry Warsawfa701a81997-01-16 00:15:11 +00003028
3029/* all errors will be checked in one fell swoop in init_tkinter() */
3030static void
Fred Drake509d79a2000-07-08 04:04:38 +00003031ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003032{
3033 PyObject *v = PyInt_FromLong(val);
3034 if (v) {
3035 PyDict_SetItemString(d, name, v);
3036 Py_DECREF(v);
3037 }
3038}
3039static void
Fred Drake509d79a2000-07-08 04:04:38 +00003040ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003041{
3042 PyObject *v = PyString_FromString(val);
3043 if (v) {
3044 PyDict_SetItemString(d, name, v);
3045 Py_DECREF(v);
3046 }
3047}
3048
3049
Mark Hammond62b1ab12002-07-23 06:31:15 +00003050PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003051init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003052{
Barry Warsawfa701a81997-01-16 00:15:11 +00003053 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003054
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00003055 Py_Type(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003056
3057#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003058 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003059#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003060
Barry Warsawfa701a81997-01-16 00:15:11 +00003061 m = Py_InitModule("_tkinter", moduleMethods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00003062 if (m == NULL)
3063 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003064
Barry Warsawfa701a81997-01-16 00:15:11 +00003065 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003066 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003067 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003068
Guido van Rossum35d43371997-08-02 00:09:09 +00003069 ins_long(d, "READABLE", TCL_READABLE);
3070 ins_long(d, "WRITABLE", TCL_WRITABLE);
3071 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3072 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3073 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3074 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3075 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3076 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3077 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003078 ins_string(d, "TK_VERSION", TK_VERSION);
3079 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003080
Guido van Rossum83551bf1997-09-13 00:44:23 +00003081 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003082
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00003083 Py_Type(&Tktt_Type) = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003084 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3085
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00003086 Py_Type(&PyTclObject_Type) = &PyType_Type;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003087 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003088
3089#ifdef TK_AQUA
3090 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3091 * start waking up. Note that Tcl_FindExecutable will do this, this
3092 * code must be above it! The original warning from
3093 * tkMacOSXAppInit.c is copied below.
3094 *
3095 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3096 * Tcl interpreter for now. It probably should work to do this
3097 * in the other order, but for now it doesn't seem to.
3098 *
3099 */
3100 Tk_MacOSXSetupTkNotifier();
3101#endif
3102
3103
Guido van Rossume187b0e2000-03-27 21:46:29 +00003104 /* This helps the dynamic loader; in Unicode aware Tcl versions
3105 it also helps Tcl find its encodings. */
3106 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003107
Barry Warsawfa701a81997-01-16 00:15:11 +00003108 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003109 return;
3110
Guido van Rossum43ff8681998-07-14 18:02:13 +00003111#if 0
3112 /* This was not a good idea; through <Destroy> bindings,
3113 Tcl_Finalize() may invoke Python code but at that point the
3114 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003115 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003116#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003117
Guido van Rossum18468821994-06-20 07:49:28 +00003118}