blob: e9dc72bb02a1bd6646c71a0332cc6d7481f402ca [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;
Barry Warsawfa701a81997-01-16 00:15:11 +00001949 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001950 int i, rv;
1951 char *s;
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
Barry Warsawfa701a81997-01-16 00:15:11 +00001978 if (!(tmp = PyList_New(0))) {
1979 Py_DECREF(res);
1980 return PythonCmd_Error(interp);
1981 }
1982
Guido van Rossum2834b972000-10-06 16:58:26 +00001983 s = AsString(res, tmp);
1984 if (s == NULL) {
1985 rv = PythonCmd_Error(interp);
1986 }
1987 else {
1988 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1989 rv = TCL_OK;
1990 }
1991
Barry Warsawfa701a81997-01-16 00:15:11 +00001992 Py_DECREF(res);
1993 Py_DECREF(tmp);
1994
Guido van Rossum00d93061998-05-28 23:06:38 +00001995 LEAVE_PYTHON
1996
Guido van Rossum2834b972000-10-06 16:58:26 +00001997 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001998}
1999
2000static void
Fred Drake509d79a2000-07-08 04:04:38 +00002001PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002002{
Guido van Rossum00d93061998-05-28 23:06:38 +00002003 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2004
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002005 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002006 Py_XDECREF(data->self);
2007 Py_XDECREF(data->func);
2008 PyMem_DEL(data);
2009 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002010}
2011
Barry Warsawfa701a81997-01-16 00:15:11 +00002012
2013
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002014
2015TCL_DECLARE_MUTEX(command_mutex)
2016
2017typedef struct CommandEvent{
2018 Tcl_Event ev;
2019 Tcl_Interp* interp;
2020 char *name;
2021 int create;
2022 int *status;
2023 ClientData *data;
2024 Tcl_Condition done;
2025} CommandEvent;
2026
2027static int
2028Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002029{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002030 if (ev->create)
2031 *ev->status = Tcl_CreateCommand(
2032 ev->interp, ev->name, PythonCmd,
2033 ev->data, PythonCmdDelete) == NULL;
2034 else
2035 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2036 Tcl_MutexLock(&command_mutex);
2037 Tcl_ConditionNotify(&ev->done);
2038 Tcl_MutexUnlock(&command_mutex);
2039 return 1;
2040}
2041
2042static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002043Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002044{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002045 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002046 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002047 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002048 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002049 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002050
Guido van Rossum43713e52000-02-29 13:59:29 +00002051 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002052 return NULL;
2053 if (!PyCallable_Check(func)) {
2054 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002055 return NULL;
2056 }
Guido van Rossum18468821994-06-20 07:49:28 +00002057
Martin v. Löwisa9656492003-03-30 08:44:58 +00002058#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002059 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002060 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002061 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002062#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002063
Guido van Rossum00d93061998-05-28 23:06:38 +00002064 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002065 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002066 return PyErr_NoMemory();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002067 Py_INCREF(self);
2068 Py_INCREF(func);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002069 data->self = selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002070 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002071
2072 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2073 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2074 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2075 ev->interp = self->interp;
2076 ev->create = 1;
2077 ev->name = cmdName;
2078 ev->data = (ClientData)data;
2079 ev->status = &err;
2080 ev->done = NULL;
2081 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2082 }
2083 else {
2084 ENTER_TCL
2085 err = Tcl_CreateCommand(
2086 Tkapp_Interp(self), cmdName, PythonCmd,
2087 (ClientData)data, PythonCmdDelete) == NULL;
2088 LEAVE_TCL
2089 }
2090 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002091 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002092 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002093 return NULL;
2094 }
Guido van Rossum18468821994-06-20 07:49:28 +00002095
Barry Warsawfa701a81997-01-16 00:15:11 +00002096 Py_INCREF(Py_None);
2097 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002098}
2099
Barry Warsawfa701a81997-01-16 00:15:11 +00002100
2101
Guido van Rossum18468821994-06-20 07:49:28 +00002102static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002103Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002104{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002105 TkappObject *self = (TkappObject*)selfptr;
Barry Warsawfa701a81997-01-16 00:15:11 +00002106 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002107 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002108
Guido van Rossum43713e52000-02-29 13:59:29 +00002109 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002110 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002111 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2112 CommandEvent *ev;
2113 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2114 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2115 ev->interp = self->interp;
2116 ev->create = 0;
2117 ev->name = cmdName;
2118 ev->status = &err;
2119 ev->done = NULL;
2120 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2121 &command_mutex);
2122 }
2123 else {
2124 ENTER_TCL
2125 err = Tcl_DeleteCommand(self->interp, cmdName);
2126 LEAVE_TCL
2127 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002128 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002129 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2130 return NULL;
2131 }
2132 Py_INCREF(Py_None);
2133 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002134}
2135
Barry Warsawfa701a81997-01-16 00:15:11 +00002136
2137
Guido van Rossum00d93061998-05-28 23:06:38 +00002138#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002139/** File Handler **/
2140
Guido van Rossum00d93061998-05-28 23:06:38 +00002141typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002142 PyObject *func;
2143 PyObject *file;
2144 int id;
2145 struct _fhcdata *next;
2146} FileHandler_ClientData;
2147
2148static FileHandler_ClientData *HeadFHCD;
2149
2150static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002151NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002152{
2153 FileHandler_ClientData *p;
2154 p = PyMem_NEW(FileHandler_ClientData, 1);
2155 if (p != NULL) {
2156 Py_XINCREF(func);
2157 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002158 p->func = func;
2159 p->file = file;
2160 p->id = id;
2161 p->next = HeadFHCD;
2162 HeadFHCD = p;
2163 }
2164 return p;
2165}
2166
2167static void
Fred Drake509d79a2000-07-08 04:04:38 +00002168DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002169{
2170 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002171
2172 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002173 while ((p = *pp) != NULL) {
2174 if (p->id == id) {
2175 *pp = p->next;
2176 Py_XDECREF(p->func);
2177 Py_XDECREF(p->file);
2178 PyMem_DEL(p);
2179 }
2180 else
2181 pp = &p->next;
2182 }
2183}
2184
Guido van Rossuma597dde1995-01-10 20:56:29 +00002185static void
Fred Drake509d79a2000-07-08 04:04:38 +00002186FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002187{
Guido van Rossum00d93061998-05-28 23:06:38 +00002188 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002189 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002190
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002191 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002192 func = data->func;
2193 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002194
Barry Warsawfa701a81997-01-16 00:15:11 +00002195 arg = Py_BuildValue("(Oi)", file, (long) mask);
2196 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002197 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002198
2199 if (res == NULL) {
2200 errorInCmd = 1;
2201 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2202 }
2203 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002204 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002205}
2206
Guido van Rossum18468821994-06-20 07:49:28 +00002207static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002208Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2209 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002210{
Guido van Rossum00d93061998-05-28 23:06:38 +00002211 FileHandler_ClientData *data;
2212 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002213 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002214
Guido van Rossum2834b972000-10-06 16:58:26 +00002215 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2216 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002217 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002218
Martin v. Löwisa9656492003-03-30 08:44:58 +00002219#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002220 if (!self && !tcl_lock) {
2221 /* We don't have the Tcl lock since Tcl is threaded. */
2222 PyErr_SetString(PyExc_RuntimeError,
2223 "_tkinter.createfilehandler not supported "
2224 "for threaded Tcl");
2225 return NULL;
2226 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002227#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002228
2229 if (self) {
2230 CHECK_TCL_APPARTMENT;
2231 }
2232
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002233 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002234 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002235 return NULL;
2236 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002237 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002238 return NULL;
2239 }
2240
Guido van Rossuma80649b2000-03-28 20:07:05 +00002241 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002242 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002243 return NULL;
2244
Barry Warsawfa701a81997-01-16 00:15:11 +00002245 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002246 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002247 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002248 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002249 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002250 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002251}
2252
2253static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002254Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002255{
Barry Warsawfa701a81997-01-16 00:15:11 +00002256 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002257 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002258
Guido van Rossum43713e52000-02-29 13:59:29 +00002259 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002260 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002261
Martin v. Löwisa9656492003-03-30 08:44:58 +00002262#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002263 if (!self && !tcl_lock) {
2264 /* We don't have the Tcl lock since Tcl is threaded. */
2265 PyErr_SetString(PyExc_RuntimeError,
2266 "_tkinter.deletefilehandler not supported "
2267 "for threaded Tcl");
2268 return NULL;
2269 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002270#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002271
2272 if (self) {
2273 CHECK_TCL_APPARTMENT;
2274 }
2275
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002276 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002277 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002278 return NULL;
2279
Guido van Rossuma80649b2000-03-28 20:07:05 +00002280 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002281
Barry Warsawfa701a81997-01-16 00:15:11 +00002282 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002283 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002284 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002285 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002286 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002287 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002288}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002289#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002290
Barry Warsawfa701a81997-01-16 00:15:11 +00002291
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002292/**** Tktt Object (timer token) ****/
2293
Jeremy Hylton938ace62002-07-17 16:30:39 +00002294static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002295
Guido van Rossum00d93061998-05-28 23:06:38 +00002296typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002297 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002298 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002299 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002300} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002301
2302static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002303Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002304{
Barry Warsawfa701a81997-01-16 00:15:11 +00002305 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002306 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002307
Guido van Rossum43713e52000-02-29 13:59:29 +00002308 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002309 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002310 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002311 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002312 v->token = NULL;
2313 }
2314 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002315 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002316 Py_DECREF(func);
2317 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002318 }
2319 Py_INCREF(Py_None);
2320 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002321}
2322
2323static PyMethodDef Tktt_methods[] =
2324{
Neal Norwitzb0493252002-03-31 14:44:22 +00002325 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002326 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002327};
2328
2329static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002330Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002331{
Barry Warsawfa701a81997-01-16 00:15:11 +00002332 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002333
Guido van Rossumb18618d2000-05-03 23:44:39 +00002334 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002335 if (v == NULL)
2336 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002337
Guido van Rossum00d93061998-05-28 23:06:38 +00002338 Py_INCREF(func);
2339 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002340 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002341
2342 /* Extra reference, deleted when called or when handler is deleted */
2343 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002344 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002345}
2346
2347static void
Fred Drake509d79a2000-07-08 04:04:38 +00002348Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002349{
Guido van Rossum00d93061998-05-28 23:06:38 +00002350 TkttObject *v = (TkttObject *)self;
2351 PyObject *func = v->func;
2352
2353 Py_XDECREF(func);
2354
Guido van Rossumb18618d2000-05-03 23:44:39 +00002355 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002356}
2357
Guido van Rossum597ac201998-05-12 14:36:19 +00002358static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002359Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002360{
Barry Warsawfa701a81997-01-16 00:15:11 +00002361 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002362 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002363
Tim Peters885d4572001-11-28 20:27:42 +00002364 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002365 v->func == NULL ? ", handler deleted" : "");
Walter Dörwald1ab83302007-05-18 17:15:44 +00002366 return PyUnicode_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002367}
2368
2369static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002370Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002371{
Barry Warsawfa701a81997-01-16 00:15:11 +00002372 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002373}
2374
2375static PyTypeObject Tktt_Type =
2376{
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00002377 PyVarObject_HEAD_INIT(NULL, 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002378 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002379 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002380 0, /*tp_itemsize */
2381 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002382 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002383 Tktt_GetAttr, /*tp_getattr */
2384 0, /*tp_setattr */
2385 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002386 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002387 0, /*tp_as_number */
2388 0, /*tp_as_sequence */
2389 0, /*tp_as_mapping */
2390 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002391};
2392
Barry Warsawfa701a81997-01-16 00:15:11 +00002393
2394
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002395/** Timer Handler **/
2396
2397static void
Fred Drake509d79a2000-07-08 04:04:38 +00002398TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002399{
Guido van Rossum00d93061998-05-28 23:06:38 +00002400 TkttObject *v = (TkttObject *)clientData;
2401 PyObject *func = v->func;
2402 PyObject *res;
2403
2404 if (func == NULL)
2405 return;
2406
2407 v->func = NULL;
2408
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002409 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002410
2411 res = PyEval_CallObject(func, NULL);
2412 Py_DECREF(func);
2413 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002414
Barry Warsawfa701a81997-01-16 00:15:11 +00002415 if (res == NULL) {
2416 errorInCmd = 1;
2417 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2418 }
2419 else
2420 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002421
2422 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002423}
2424
2425static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002426Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002427{
Barry Warsawfa701a81997-01-16 00:15:11 +00002428 int milliseconds;
2429 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002430 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002431
Guido van Rossum2834b972000-10-06 16:58:26 +00002432 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2433 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002434 return NULL;
2435 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002436 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002437 return NULL;
2438 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002439
Martin v. Löwisa9656492003-03-30 08:44:58 +00002440#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002441 if (!self && !tcl_lock) {
2442 /* We don't have the Tcl lock since Tcl is threaded. */
2443 PyErr_SetString(PyExc_RuntimeError,
2444 "_tkinter.createtimerhandler not supported "
2445 "for threaded Tcl");
2446 return NULL;
2447 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002448#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002449
2450 if (self) {
2451 CHECK_TCL_APPARTMENT;
2452 }
2453
Guido van Rossum00d93061998-05-28 23:06:38 +00002454 v = Tktt_New(func);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002455 if (v) {
2456 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2457 (ClientData)v);
2458 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002459
Guido van Rossum00d93061998-05-28 23:06:38 +00002460 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002461}
2462
Barry Warsawfa701a81997-01-16 00:15:11 +00002463
Guido van Rossum18468821994-06-20 07:49:28 +00002464/** Event Loop **/
2465
Guido van Rossum18468821994-06-20 07:49:28 +00002466static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002467Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002468{
Barry Warsawfa701a81997-01-16 00:15:11 +00002469 int threshold = 0;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002470 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002471#ifdef WITH_THREAD
2472 PyThreadState *tstate = PyThreadState_Get();
2473#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002474
Guido van Rossum43713e52000-02-29 13:59:29 +00002475 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002476 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002477
Martin v. Löwisa9656492003-03-30 08:44:58 +00002478#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002479 if (!self && !tcl_lock) {
2480 /* We don't have the Tcl lock since Tcl is threaded. */
2481 PyErr_SetString(PyExc_RuntimeError,
2482 "_tkinter.mainloop not supported "
2483 "for threaded Tcl");
2484 return NULL;
2485 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002486#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002487
2488 if (self) {
2489 CHECK_TCL_APPARTMENT;
2490 self->dispatching = 1;
2491 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002492
Barry Warsawfa701a81997-01-16 00:15:11 +00002493 quitMainLoop = 0;
2494 while (Tk_GetNumMainWindows() > threshold &&
2495 !quitMainLoop &&
2496 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002497 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002498 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002499
2500#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002501 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002502 /* Allow other Python threads to run. */
2503 ENTER_TCL
2504 result = Tcl_DoOneEvent(0);
2505 LEAVE_TCL
2506 }
2507 else {
2508 Py_BEGIN_ALLOW_THREADS
2509 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2510 tcl_tstate = tstate;
2511 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2512 tcl_tstate = NULL;
2513 if(tcl_lock)PyThread_release_lock(tcl_lock);
2514 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002515 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002516 Py_END_ALLOW_THREADS
2517 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002518#else
2519 result = Tcl_DoOneEvent(0);
2520#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002521
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002522 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002523 if (self)
2524 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002525 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002526 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002527 if (result < 0)
2528 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002529 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002530 if (self)
2531 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002532 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002533
Barry Warsawfa701a81997-01-16 00:15:11 +00002534 if (errorInCmd) {
2535 errorInCmd = 0;
2536 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2537 excInCmd = valInCmd = trbInCmd = NULL;
2538 return NULL;
2539 }
2540 Py_INCREF(Py_None);
2541 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002542}
2543
2544static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002545Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002546{
Guido van Rossum35d43371997-08-02 00:09:09 +00002547 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002548 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002549
Guido van Rossum43713e52000-02-29 13:59:29 +00002550 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002551 return NULL;
2552
Guido van Rossum00d93061998-05-28 23:06:38 +00002553 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002554 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002555 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002556 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002557}
2558
2559static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002560Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002561{
2562
Guido van Rossum43713e52000-02-29 13:59:29 +00002563 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002564 return NULL;
2565
2566 quitMainLoop = 1;
2567 Py_INCREF(Py_None);
2568 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002569}
2570
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002571static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002572Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002573{
2574
Guido van Rossum43713e52000-02-29 13:59:29 +00002575 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002576 return NULL;
2577
2578 return PyInt_FromLong((long)Tkapp_Interp(self));
2579}
2580
David Aschere2b4b322004-02-18 05:59:53 +00002581static PyObject *
2582Tkapp_TkInit(PyObject *self, PyObject *args)
2583{
Thomas Wouters477c8d52006-05-27 19:21:47 +00002584 static int has_failed;
David Aschere2b4b322004-02-18 05:59:53 +00002585 Tcl_Interp *interp = Tkapp_Interp(self);
Neal Norwitz44dbae82004-02-19 02:44:22 +00002586 Tk_Window main_window;
David Aschere2b4b322004-02-18 05:59:53 +00002587 const char * _tk_exists = NULL;
David Aschere2b4b322004-02-18 05:59:53 +00002588 int err;
Neal Norwitz44dbae82004-02-19 02:44:22 +00002589 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002590
Thomas Wouters477c8d52006-05-27 19:21:47 +00002591 /* In all current versions of Tk (including 8.4.13), Tk_Init
2592 deadlocks on the second call when the first call failed.
2593 To avoid the deadlock, we just refuse the second call through
2594 a static variable. */
2595 if (has_failed) {
2596 PyErr_SetString(Tkinter_TclError,
2597 "Calling Tk_Init again after a previous call failed might deadlock");
2598 return NULL;
2599 }
2600
David Aschere2b4b322004-02-18 05:59:53 +00002601 /* We want to guard against calling Tk_Init() multiple times */
2602 CHECK_TCL_APPARTMENT;
2603 ENTER_TCL
2604 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2605 ENTER_OVERLAP
2606 if (err == TCL_ERROR) {
Thomas Wouters477c8d52006-05-27 19:21:47 +00002607 /* This sets an exception, but we cannot return right
2608 away because we need to exit the overlap first. */
2609 Tkinter_Error(self);
David Aschere2b4b322004-02-18 05:59:53 +00002610 } else {
2611 _tk_exists = Tkapp_Result(self);
2612 }
2613 LEAVE_OVERLAP_TCL
2614 if (err == TCL_ERROR) {
2615 return NULL;
2616 }
2617 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2618 if (Tk_Init(interp) == TCL_ERROR) {
2619 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Thomas Wouters477c8d52006-05-27 19:21:47 +00002620 has_failed = 1;
David Aschere2b4b322004-02-18 05:59:53 +00002621 return NULL;
2622 }
2623 }
2624 Py_INCREF(Py_None);
2625 return Py_None;
2626}
Barry Warsawfa701a81997-01-16 00:15:11 +00002627
Martin v. Löwisffad6332002-11-26 09:28:05 +00002628static PyObject *
2629Tkapp_WantObjects(PyObject *self, PyObject *args)
2630{
2631
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002632 int wantobjects = -1;
2633 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002634 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002635 if (wantobjects == -1)
2636 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002637 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002638
2639 Py_INCREF(Py_None);
2640 return Py_None;
2641}
2642
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002643static PyObject *
2644Tkapp_WillDispatch(PyObject *self, PyObject *args)
2645{
2646
2647 ((TkappObject*)self)->dispatching = 1;
2648
2649 Py_INCREF(Py_None);
2650 return Py_None;
2651}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002652
Barry Warsawfa701a81997-01-16 00:15:11 +00002653
Guido van Rossum18468821994-06-20 07:49:28 +00002654/**** Tkapp Method List ****/
2655
2656static PyMethodDef Tkapp_methods[] =
2657{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002658 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002659 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Guido van Rossumd59da4b2007-05-22 18:11:13 +00002660 {"call", Tkapp_Call, METH_VARARGS},
2661 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002662 {"eval", Tkapp_Eval, METH_VARARGS},
2663 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2664 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2665 {"record", Tkapp_Record, METH_VARARGS},
2666 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2667 {"setvar", Tkapp_SetVar, METH_VARARGS},
2668 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2669 {"getvar", Tkapp_GetVar, METH_VARARGS},
2670 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2671 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2672 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2673 {"getint", Tkapp_GetInt, METH_VARARGS},
2674 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2675 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2676 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2677 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2678 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2679 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2680 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2681 {"split", Tkapp_Split, METH_VARARGS},
Guido van Rossumd59da4b2007-05-22 18:11:13 +00002682 {"merge", Tkapp_Merge, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002683 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2684 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002685#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002686 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2687 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002688#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002689 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2690 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2691 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2692 {"quit", Tkapp_Quit, METH_VARARGS},
2693 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Neal Norwitz44dbae82004-02-19 02:44:22 +00002694 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002695 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002696};
2697
Barry Warsawfa701a81997-01-16 00:15:11 +00002698
2699
Guido van Rossum18468821994-06-20 07:49:28 +00002700/**** Tkapp Type Methods ****/
2701
2702static void
Fred Drake509d79a2000-07-08 04:04:38 +00002703Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002704{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002705 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002706 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002707 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002708 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002709 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002710 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002711}
2712
2713static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002714Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002715{
Guido van Rossum35d43371997-08-02 00:09:09 +00002716 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002717}
2718
2719static PyTypeObject Tkapp_Type =
2720{
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00002721 PyVarObject_HEAD_INIT(NULL, 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002722 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002723 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002724 0, /*tp_itemsize */
2725 Tkapp_Dealloc, /*tp_dealloc */
2726 0, /*tp_print */
2727 Tkapp_GetAttr, /*tp_getattr */
2728 0, /*tp_setattr */
2729 0, /*tp_compare */
2730 0, /*tp_repr */
2731 0, /*tp_as_number */
2732 0, /*tp_as_sequence */
2733 0, /*tp_as_mapping */
2734 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002735};
2736
Barry Warsawfa701a81997-01-16 00:15:11 +00002737
2738
Guido van Rossum18468821994-06-20 07:49:28 +00002739/**** Tkinter Module ****/
2740
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002741typedef struct {
2742 PyObject* tuple;
2743 int size; /* current size */
2744 int maxsize; /* allocated size */
2745} FlattenContext;
2746
2747static int
2748_bump(FlattenContext* context, int size)
2749{
Guido van Rossum2834b972000-10-06 16:58:26 +00002750 /* expand tuple to hold (at least) size new items.
2751 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002752
2753 int maxsize = context->maxsize * 2;
2754
2755 if (maxsize < context->size + size)
2756 maxsize = context->size + size;
2757
2758 context->maxsize = maxsize;
2759
Tim Peters4324aa32001-05-28 22:30:08 +00002760 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002761}
2762
2763static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002764_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002765{
2766 /* add tuple or list to argument tuple (recursively) */
2767
2768 int i, size;
2769
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002770 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002771 PyErr_SetString(PyExc_ValueError,
2772 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002773 return 0;
2774 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002775 size = PyList_GET_SIZE(item);
2776 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002777 if (context->size + size > context->maxsize &&
2778 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002779 return 0;
2780 /* copy items to output tuple */
2781 for (i = 0; i < size; i++) {
2782 PyObject *o = PyList_GET_ITEM(item, i);
2783 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002784 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002785 return 0;
2786 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002787 if (context->size + 1 > context->maxsize &&
2788 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002789 return 0;
2790 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002791 PyTuple_SET_ITEM(context->tuple,
2792 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002793 }
2794 }
2795 } else if (PyTuple_Check(item)) {
2796 /* same, for tuples */
2797 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002798 if (context->size + size > context->maxsize &&
2799 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002800 return 0;
2801 for (i = 0; i < size; i++) {
2802 PyObject *o = PyTuple_GET_ITEM(item, i);
2803 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002804 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002805 return 0;
2806 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002807 if (context->size + 1 > context->maxsize &&
2808 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002809 return 0;
2810 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002811 PyTuple_SET_ITEM(context->tuple,
2812 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002813 }
2814 }
2815 } else {
2816 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2817 return 0;
2818 }
2819 return 1;
2820}
2821
2822static PyObject *
2823Tkinter_Flatten(PyObject* self, PyObject* args)
2824{
2825 FlattenContext context;
2826 PyObject* item;
2827
2828 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2829 return NULL;
2830
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002831 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002832 if (context.maxsize <= 0)
2833 return PyTuple_New(0);
2834
2835 context.tuple = PyTuple_New(context.maxsize);
2836 if (!context.tuple)
2837 return NULL;
2838
2839 context.size = 0;
2840
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002841 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002842 return NULL;
2843
Tim Peters4324aa32001-05-28 22:30:08 +00002844 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002845 return NULL;
2846
2847 return context.tuple;
2848}
2849
Guido van Rossum18468821994-06-20 07:49:28 +00002850static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002851Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002852{
Barry Warsawfa701a81997-01-16 00:15:11 +00002853 char *screenName = NULL;
2854 char *baseName = NULL;
2855 char *className = NULL;
2856 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002857 int wantobjects = 0;
David Aschere2b4b322004-02-18 05:59:53 +00002858 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002859 int sync = 0; /* pass -sync to wish */
2860 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002861
Guido van Rossum35d43371997-08-02 00:09:09 +00002862 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002863 if (baseName != NULL)
2864 baseName++;
2865 else
2866 baseName = Py_GetProgramName();
2867 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002868
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002869 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002870 &screenName, &baseName, &className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002871 &interactive, &wantobjects, &wantTk,
2872 &sync, &use))
Barry Warsawfa701a81997-01-16 00:15:11 +00002873 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002874
Barry Warsawfa701a81997-01-16 00:15:11 +00002875 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002876 interactive, wantobjects, wantTk,
2877 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002878}
2879
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002880static PyObject *
2881Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2882{
2883 int new_val;
2884 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2885 return NULL;
2886 if (new_val < 0) {
2887 PyErr_SetString(PyExc_ValueError,
2888 "busywaitinterval must be >= 0");
2889 return NULL;
2890 }
2891 Tkinter_busywaitinterval = new_val;
2892 Py_INCREF(Py_None);
2893 return Py_None;
2894}
2895
2896static char setbusywaitinterval_doc[] =
2897"setbusywaitinterval(n) -> None\n\
2898\n\
2899Set the busy-wait interval in milliseconds between successive\n\
2900calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2901It should be set to a divisor of the maximum time between\n\
2902frames in an animation.";
2903
2904static PyObject *
2905Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2906{
2907 return PyInt_FromLong(Tkinter_busywaitinterval);
2908}
2909
2910static char getbusywaitinterval_doc[] =
2911"getbusywaitinterval() -> int\n\
2912\n\
2913Return the current busy-wait interval between successive\n\
2914calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2915
Guido van Rossum18468821994-06-20 07:49:28 +00002916static PyMethodDef moduleMethods[] =
2917{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002918 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2919 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002920#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002921 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2922 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002923#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002924 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2925 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2926 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2927 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002928 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2929 setbusywaitinterval_doc},
2930 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2931 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002932 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002933};
2934
Guido van Rossum7bf15641998-05-22 18:28:17 +00002935#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002936
2937static int stdin_ready = 0;
2938
Guido van Rossumad4db171998-06-13 13:56:28 +00002939#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002940static void
Fred Drake509d79a2000-07-08 04:04:38 +00002941MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002942{
2943 stdin_ready = 1;
2944}
Guido van Rossumad4db171998-06-13 13:56:28 +00002945#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002946
Martin v. Löwisa9656492003-03-30 08:44:58 +00002947#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002948static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002949#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002950
Guido van Rossum18468821994-06-20 07:49:28 +00002951static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002952EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002953{
Guido van Rossumad4db171998-06-13 13:56:28 +00002954#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002955 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002956#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002957#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002958 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002959#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002960 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002961 errorInCmd = 0;
2962#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002963 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002964 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002965#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002966 while (!errorInCmd && !stdin_ready) {
2967 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002968#ifdef MS_WINDOWS
2969 if (_kbhit()) {
2970 stdin_ready = 1;
2971 break;
2972 }
2973#endif
2974#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002975 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002976 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002977 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002978
Guido van Rossum00d93061998-05-28 23:06:38 +00002979 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002980
2981 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002982 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002983 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002984 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002985 Py_END_ALLOW_THREADS
2986#else
2987 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002988#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002989
2990 if (result < 0)
2991 break;
2992 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002993#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002994 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002995#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002996 if (errorInCmd) {
2997 errorInCmd = 0;
2998 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2999 excInCmd = valInCmd = trbInCmd = NULL;
3000 PyErr_Print();
3001 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003002#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00003003 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003004#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003005 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003006}
Guido van Rossum18468821994-06-20 07:49:28 +00003007
Guido van Rossum00d93061998-05-28 23:06:38 +00003008#endif
3009
Guido van Rossum7bf15641998-05-22 18:28:17 +00003010static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003011EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003012{
Guido van Rossum00d93061998-05-28 23:06:38 +00003013#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003014 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003015#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003016 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003017#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003018 PyOS_InputHook = EventHook;
3019 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003020#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003021}
3022
3023static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003024DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003025{
Guido van Rossum00d93061998-05-28 23:06:38 +00003026#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003027 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3028 PyOS_InputHook = NULL;
3029 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003030#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003031}
3032
Barry Warsawfa701a81997-01-16 00:15:11 +00003033
3034/* all errors will be checked in one fell swoop in init_tkinter() */
3035static void
Fred Drake509d79a2000-07-08 04:04:38 +00003036ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003037{
3038 PyObject *v = PyInt_FromLong(val);
3039 if (v) {
3040 PyDict_SetItemString(d, name, v);
3041 Py_DECREF(v);
3042 }
3043}
3044static void
Fred Drake509d79a2000-07-08 04:04:38 +00003045ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003046{
3047 PyObject *v = PyString_FromString(val);
3048 if (v) {
3049 PyDict_SetItemString(d, name, v);
3050 Py_DECREF(v);
3051 }
3052}
3053
3054
Mark Hammond62b1ab12002-07-23 06:31:15 +00003055PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003056init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003057{
Barry Warsawfa701a81997-01-16 00:15:11 +00003058 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003059
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00003060 Py_Type(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003061
3062#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003063 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003064#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003065
Barry Warsawfa701a81997-01-16 00:15:11 +00003066 m = Py_InitModule("_tkinter", moduleMethods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00003067 if (m == NULL)
3068 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003069
Barry Warsawfa701a81997-01-16 00:15:11 +00003070 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003071 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003072 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003073
Guido van Rossum35d43371997-08-02 00:09:09 +00003074 ins_long(d, "READABLE", TCL_READABLE);
3075 ins_long(d, "WRITABLE", TCL_WRITABLE);
3076 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3077 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3078 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3079 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3080 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3081 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3082 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003083 ins_string(d, "TK_VERSION", TK_VERSION);
3084 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003085
Guido van Rossum83551bf1997-09-13 00:44:23 +00003086 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003087
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00003088 Py_Type(&Tktt_Type) = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003089 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3090
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00003091 Py_Type(&PyTclObject_Type) = &PyType_Type;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003092 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003093
3094#ifdef TK_AQUA
3095 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3096 * start waking up. Note that Tcl_FindExecutable will do this, this
3097 * code must be above it! The original warning from
3098 * tkMacOSXAppInit.c is copied below.
3099 *
3100 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3101 * Tcl interpreter for now. It probably should work to do this
3102 * in the other order, but for now it doesn't seem to.
3103 *
3104 */
3105 Tk_MacOSXSetupTkNotifier();
3106#endif
3107
3108
Guido van Rossume187b0e2000-03-27 21:46:29 +00003109 /* This helps the dynamic loader; in Unicode aware Tcl versions
3110 it also helps Tcl find its encodings. */
3111 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003112
Barry Warsawfa701a81997-01-16 00:15:11 +00003113 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003114 return;
3115
Guido van Rossum43ff8681998-07-14 18:02:13 +00003116#if 0
3117 /* This was not a good idea; through <Destroy> bindings,
3118 Tcl_Finalize() may invoke Python code but at that point the
3119 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003120 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003121#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003122
Guido van Rossum18468821994-06-20 07:49:28 +00003123}