blob: deb7f1cec96a183fa131cd064a44986fcc993fee [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
265#define Tkapp_Check(v) ((v)->ob_type == &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", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000270(void *) v, ((PyObject *) v)->ob_refcnt))
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öwisffad6332002-11-26 09:28:05 +0000831 PyObject_HEAD_INIT(NULL)
832 0, /*ob_size*/
833 "_tkinter.Tcl_Obj", /*tp_name*/
834 sizeof(PyTclObject), /*tp_basicsize*/
835 0, /*tp_itemsize*/
836 /* methods */
837 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
838 0, /*tp_print*/
839 0, /*tp_getattr*/
840 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000841 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000842 (reprfunc)PyTclObject_repr, /*tp_repr*/
843 0, /*tp_as_number*/
844 0, /*tp_as_sequence*/
845 0, /*tp_as_mapping*/
846 0, /*tp_hash*/
847 0, /*tp_call*/
848 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000849 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000850 0, /*tp_setattro*/
851 0, /*tp_as_buffer*/
852 Py_TPFLAGS_DEFAULT, /*tp_flags*/
853 0, /*tp_doc*/
854 0, /*tp_traverse*/
855 0, /*tp_clear*/
856 0, /*tp_richcompare*/
857 0, /*tp_weaklistoffset*/
858 0, /*tp_iter*/
859 0, /*tp_iternext*/
Walter Dörwald6720d912007-07-12 12:12:25 +0000860 0, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000861 0, /*tp_members*/
862 PyTclObject_getsetlist, /*tp_getset*/
863 0, /*tp_base*/
864 0, /*tp_dict*/
865 0, /*tp_descr_get*/
866 0, /*tp_descr_set*/
867 0, /*tp_dictoffset*/
868 0, /*tp_init*/
869 0, /*tp_alloc*/
870 0, /*tp_new*/
871 0, /*tp_free*/
872 0, /*tp_is_gc*/
873};
874
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000875static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000876AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000877{
878 Tcl_Obj *result;
879
880 if (PyString_Check(value))
881 return Tcl_NewStringObj(PyString_AS_STRING(value),
882 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000883 else if (PyBool_Check(value))
884 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossumddefaf32007-01-14 03:31:43 +0000885 else if (PyInt_CheckExact(value))
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000886 return Tcl_NewLongObj(PyInt_AS_LONG(value));
887 else if (PyFloat_Check(value))
888 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
889 else if (PyTuple_Check(value)) {
890 Tcl_Obj **argv = (Tcl_Obj**)
891 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
892 int i;
893 if(!argv)
894 return 0;
895 for(i=0;i<PyTuple_Size(value);i++)
896 argv[i] = AsObj(PyTuple_GetItem(value,i));
897 result = Tcl_NewListObj(PyTuple_Size(value), argv);
898 ckfree(FREECAST argv);
899 return result;
900 }
901 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000902 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000903 Py_ssize_t size = PyUnicode_GET_SIZE(value);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000904 /* This #ifdef assumes that Tcl uses UCS-2.
905 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000906#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000907 Tcl_UniChar *outbuf;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000908 Py_ssize_t i;
909 assert(size < size * sizeof(Tcl_UniChar));
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000910 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
911 if (!outbuf) {
912 PyErr_NoMemory();
913 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000914 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000915 for (i = 0; i < size; i++) {
916 if (inbuf[i] >= 0x10000) {
917 /* Tcl doesn't do UTF-16, yet. */
918 PyErr_SetString(PyExc_ValueError,
919 "unsupported character");
920 ckfree(FREECAST outbuf);
921 return NULL;
922 }
923 outbuf[i] = inbuf[i];
924 }
925 result = Tcl_NewUnicodeObj(outbuf, size);
926 ckfree(FREECAST outbuf);
927 return result;
928#else
929 return Tcl_NewUnicodeObj(inbuf, size);
930#endif
931
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000932 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000933 else if(PyTclObject_Check(value)) {
934 Tcl_Obj *v = ((PyTclObject*)value)->value;
935 Tcl_IncrRefCount(v);
936 return v;
937 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000938 else {
939 PyObject *v = PyObject_Str(value);
940 if (!v)
941 return 0;
942 result = AsObj(v);
943 Py_DECREF(v);
944 return result;
945 }
946}
947
Martin v. Löwisffad6332002-11-26 09:28:05 +0000948static PyObject*
949FromObj(PyObject* tkapp, Tcl_Obj *value)
950{
951 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000952 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000953
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000954 if (value->typePtr == NULL) {
955 /* If the result contains any bytes with the top bit set,
956 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000957 int i;
958 char *s = value->bytes;
959 int len = value->length;
960 for (i = 0; i < len; i++) {
961 if (value->bytes[i] & 0x80)
962 break;
963 }
964
965 if (i == value->length)
966 result = PyString_FromStringAndSize(s, len);
967 else {
968 /* Convert UTF-8 to Unicode string */
969 result = PyUnicode_DecodeUTF8(s, len, "strict");
970 if (result == NULL) {
971 PyErr_Clear();
972 result = PyString_FromStringAndSize(s, len);
973 }
974 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000975 return result;
976 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000977
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000978 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000979 result = value->internalRep.longValue ? Py_True : Py_False;
980 Py_INCREF(result);
981 return result;
982 }
983
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000984 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000985 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000986 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000987 return PyString_FromStringAndSize(data, size);
988 }
989
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000990 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000991 return PyFloat_FromDouble(value->internalRep.doubleValue);
992 }
993
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000994 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000995 return PyInt_FromLong(value->internalRep.longValue);
996 }
997
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000998 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000999 int size;
1000 int i, status;
1001 PyObject *elem;
1002 Tcl_Obj *tcl_elem;
1003
1004 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1005 if (status == TCL_ERROR)
1006 return Tkinter_Error(tkapp);
1007 result = PyTuple_New(size);
1008 if (!result)
1009 return NULL;
1010 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001011 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001012 value, i, &tcl_elem);
1013 if (status == TCL_ERROR) {
1014 Py_DECREF(result);
1015 return Tkinter_Error(tkapp);
1016 }
1017 elem = FromObj(tkapp, tcl_elem);
1018 if (!elem) {
1019 Py_DECREF(result);
1020 return NULL;
1021 }
1022 PyTuple_SetItem(result, i, elem);
1023 }
1024 return result;
1025 }
1026
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001027 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001028 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001029 }
1030
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001031 if (value->typePtr == app->StringType) {
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001032#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001033 PyObject *result;
1034 int size;
1035 Tcl_UniChar *input;
1036 Py_UNICODE *output;
1037
1038 size = Tcl_GetCharLength(value);
1039 result = PyUnicode_FromUnicode(NULL, size);
1040 if (!result)
1041 return NULL;
1042 input = Tcl_GetUnicode(value);
1043 output = PyUnicode_AS_UNICODE(result);
1044 while (size--)
1045 *output++ = *input++;
1046 return result;
1047#else
1048 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1049 Tcl_GetCharLength(value));
1050#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +00001051 }
1052
1053 return newPyTclObject(value);
1054}
1055
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001056/* This mutex synchronizes inter-thread command calls. */
1057
1058TCL_DECLARE_MUTEX(call_mutex)
1059
1060typedef struct Tkapp_CallEvent {
1061 Tcl_Event ev; /* Must be first */
1062 TkappObject *self;
1063 PyObject *args;
1064 int flags;
1065 PyObject **res;
1066 PyObject **exc_type, **exc_value, **exc_tb;
1067 Tcl_Condition done;
1068} Tkapp_CallEvent;
1069
1070void
1071Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001072{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001073 int i;
1074 for (i = 0; i < objc; i++)
1075 Tcl_DecrRefCount(objv[i]);
1076 if (objv != objStore)
1077 ckfree(FREECAST objv);
1078}
Guido van Rossum18468821994-06-20 07:49:28 +00001079
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001080/* Convert Python objects to Tcl objects. This must happen in the
1081 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001082
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001083static Tcl_Obj**
1084Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1085{
1086 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001087 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001088 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001089 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001090
Guido van Rossum212643f1998-04-29 16:22:14 +00001091 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001092 objv[0] = AsObj(args);
1093 if (objv[0] == 0)
1094 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001095 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001096 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001097 }
1098 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001099 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001100
Guido van Rossum632de272000-03-29 00:19:50 +00001101 if (objc > ARGSZ) {
1102 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1103 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001104 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001105 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001106 goto finally;
1107 }
1108 }
1109
Guido van Rossum632de272000-03-29 00:19:50 +00001110 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001111 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001112 if (v == Py_None) {
1113 objc = i;
1114 break;
1115 }
Guido van Rossum632de272000-03-29 00:19:50 +00001116 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001117 if (!objv[i]) {
1118 /* Reset objc, so it attempts to clear
1119 objects only up to i. */
1120 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001121 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001122 }
Guido van Rossum632de272000-03-29 00:19:50 +00001123 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001124 }
1125 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001126 *pobjc = objc;
1127 return objv;
1128finally:
1129 Tkapp_CallDeallocArgs(objv, objStore, objc);
1130 return NULL;
1131}
Guido van Rossum212643f1998-04-29 16:22:14 +00001132
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001133/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001134
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001135static PyObject*
1136Tkapp_CallResult(TkappObject *self)
1137{
1138 PyObject *res = NULL;
1139 if(self->wantobjects) {
1140 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001141 /* Not sure whether the IncrRef is necessary, but something
1142 may overwrite the interpreter result while we are
1143 converting it. */
1144 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001145 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001146 Tcl_DecrRefCount(value);
1147 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001148 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001149 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001150
Guido van Rossum990f5c62000-05-04 15:07:16 +00001151 /* If the result contains any bytes with the top bit set,
1152 it's UTF-8 and we should decode it to Unicode */
1153 while (*p != '\0') {
1154 if (*p & 0x80)
1155 break;
1156 p++;
1157 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001158
Guido van Rossum990f5c62000-05-04 15:07:16 +00001159 if (*p == '\0')
1160 res = PyString_FromStringAndSize(s, (int)(p-s));
1161 else {
1162 /* Convert UTF-8 to Unicode string */
1163 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001164 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1165 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001166 PyErr_Clear();
1167 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001168 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001169 }
1170 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001171 return res;
1172}
Guido van Rossum632de272000-03-29 00:19:50 +00001173
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001174/* Tkapp_CallProc is the event procedure that is executed in the context of
1175 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1176 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001177
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001178static int
1179Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1180{
1181 Tcl_Obj *objStore[ARGSZ];
1182 Tcl_Obj **objv;
1183 int objc;
1184 int i;
1185 ENTER_PYTHON
1186 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1187 if (!objv) {
1188 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1189 *(e->res) = NULL;
1190 }
1191 LEAVE_PYTHON
1192 if (!objv)
1193 goto done;
1194 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1195 ENTER_PYTHON
1196 if (i == TCL_ERROR) {
1197 *(e->res) = NULL;
1198 *(e->exc_type) = NULL;
1199 *(e->exc_tb) = NULL;
1200 *(e->exc_value) = PyObject_CallFunction(
1201 Tkinter_TclError, "s",
1202 Tcl_GetStringResult(e->self->interp));
1203 }
1204 else {
1205 *(e->res) = Tkapp_CallResult(e->self);
1206 }
1207 LEAVE_PYTHON
1208 done:
1209 /* Wake up calling thread. */
1210 Tcl_MutexLock(&call_mutex);
1211 Tcl_ConditionNotify(&e->done);
1212 Tcl_MutexUnlock(&call_mutex);
1213 return 1;
1214}
1215
1216/* This is the main entry point for calling a Tcl command.
1217 It supports three cases, with regard to threading:
1218 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1219 the context of the calling thread.
1220 2. Tcl is threaded, caller of the command is in the interpreter thread:
1221 Execute the command in the calling thread. Since the Tcl lock will
1222 not be used, we can merge that with case 1.
1223 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1224 the interpreter thread. Allocation of Tcl objects needs to occur in the
1225 interpreter thread, so we ship the PyObject* args to the target thread,
1226 and perform processing there. */
1227
1228static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001229Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001230{
1231 Tcl_Obj *objStore[ARGSZ];
1232 Tcl_Obj **objv = NULL;
1233 int objc, i;
1234 PyObject *res = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001235 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001236 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1237 int flags = TCL_EVAL_DIRECT;
1238
Guido van Rossum992d4a32007-07-11 13:09:30 +00001239 /* If args is a single tuple, replace with contents of tuple */
1240 if (1 == PyTuple_Size(args)){
1241 PyObject* item = PyTuple_GetItem(args, 0);
1242 if (PyTuple_Check(item))
1243 args = item;
1244 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001245#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001246 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1247 /* We cannot call the command directly. Instead, we must
1248 marshal the parameters to the interpreter thread. */
1249 Tkapp_CallEvent *ev;
1250 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001251 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001252 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001253 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1254 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1255 ev->self = self;
1256 ev->args = args;
1257 ev->res = &res;
1258 ev->exc_type = &exc_type;
1259 ev->exc_value = &exc_value;
1260 ev->exc_tb = &exc_tb;
1261 ev->done = (Tcl_Condition)0;
1262
1263 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1264
1265 if (res == NULL) {
1266 if (exc_type)
1267 PyErr_Restore(exc_type, exc_value, exc_tb);
1268 else
1269 PyErr_SetObject(Tkinter_TclError, exc_value);
1270 }
1271 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001272 else
1273#endif
1274 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001275
1276 objv = Tkapp_CallArgs(args, objStore, &objc);
1277 if (!objv)
1278 return NULL;
1279
1280 ENTER_TCL
1281
1282 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1283
1284 ENTER_OVERLAP
1285
1286 if (i == TCL_ERROR)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001287 Tkinter_Error(selfptr);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001288 else
1289 res = Tkapp_CallResult(self);
1290
1291 LEAVE_OVERLAP_TCL
1292
1293 Tkapp_CallDeallocArgs(objv, objStore, objc);
1294 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001295 return res;
1296}
1297
1298
1299static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001300Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001301{
Guido van Rossum212643f1998-04-29 16:22:14 +00001302 /* Could do the same here as for Tkapp_Call(), but this is not used
1303 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1304 way for the user to do what all its Global* variants do (save and
1305 reset the scope pointer, call the local version, restore the saved
1306 scope pointer). */
1307
Guido van Rossum62320c91998-06-15 04:36:09 +00001308 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001309 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001310
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001311 CHECK_TCL_APPARTMENT;
1312
Guido van Rossum62320c91998-06-15 04:36:09 +00001313 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001314 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001315 int err;
1316 ENTER_TCL
1317 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001318 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001319 if (err == TCL_ERROR)
1320 res = Tkinter_Error(self);
1321 else
1322 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001323 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001324 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001325 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001326
1327 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001328}
1329
1330static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001331Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001332{
Barry Warsawfa701a81997-01-16 00:15:11 +00001333 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001334 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001335 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001336
Guido van Rossum43713e52000-02-29 13:59:29 +00001337 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001338 return NULL;
1339
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001340 CHECK_TCL_APPARTMENT;
1341
Guido van Rossum00d93061998-05-28 23:06:38 +00001342 ENTER_TCL
1343 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001344 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001345 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001346 res = Tkinter_Error(self);
1347 else
1348 res = PyString_FromString(Tkapp_Result(self));
1349 LEAVE_OVERLAP_TCL
1350 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001351}
1352
1353static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001354Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001355{
Barry Warsawfa701a81997-01-16 00:15:11 +00001356 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001357 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001358 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001359
Guido van Rossum43713e52000-02-29 13:59:29 +00001360 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001361 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001362
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001363 CHECK_TCL_APPARTMENT;
1364
Guido van Rossum00d93061998-05-28 23:06:38 +00001365 ENTER_TCL
1366 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001367 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001368 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001369 res = Tkinter_Error(self);
1370 else
1371 res = PyString_FromString(Tkapp_Result(self));
1372 LEAVE_OVERLAP_TCL
1373 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001374}
1375
1376static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001377Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001378{
Barry Warsawfa701a81997-01-16 00:15:11 +00001379 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001380 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001381 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001382
Guido van Rossum43713e52000-02-29 13:59:29 +00001383 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001384 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001385
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001386 CHECK_TCL_APPARTMENT;
1387
Guido van Rossum00d93061998-05-28 23:06:38 +00001388 ENTER_TCL
1389 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001390 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001391 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001392 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001393
Guido van Rossum62320c91998-06-15 04:36:09 +00001394 else
1395 res = PyString_FromString(Tkapp_Result(self));
1396 LEAVE_OVERLAP_TCL
1397 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001398}
1399
1400static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001401Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001402{
Barry Warsawfa701a81997-01-16 00:15:11 +00001403 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001404 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001405 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001406
Guido van Rossum35d43371997-08-02 00:09:09 +00001407 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001408 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001409
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001410 CHECK_TCL_APPARTMENT;
1411
Guido van Rossum00d93061998-05-28 23:06:38 +00001412 ENTER_TCL
1413 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001414 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001415 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001416 res = Tkinter_Error(self);
1417 else
1418 res = PyString_FromString(Tkapp_Result(self));
1419 LEAVE_OVERLAP_TCL
1420 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001421}
1422
1423static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001424Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001425{
Barry Warsawfa701a81997-01-16 00:15:11 +00001426 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001427
Guido van Rossum43713e52000-02-29 13:59:29 +00001428 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001429 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001430 CHECK_TCL_APPARTMENT;
1431
Guido van Rossum00d93061998-05-28 23:06:38 +00001432 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001433 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001434 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001435
Barry Warsawfa701a81997-01-16 00:15:11 +00001436 Py_INCREF(Py_None);
1437 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001438}
1439
Barry Warsawfa701a81997-01-16 00:15:11 +00001440
1441
Guido van Rossum18468821994-06-20 07:49:28 +00001442/** Tcl Variable **/
1443
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001444TCL_DECLARE_MUTEX(var_mutex)
1445
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001446typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001447typedef struct VarEvent {
1448 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001449 PyObject *self;
1450 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001451 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001452 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001453 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001454 PyObject **exc_type;
1455 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001456 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001457} VarEvent;
1458
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001459static int
1460varname_converter(PyObject *in, void *_out)
1461{
1462 char **out = (char**)_out;
1463 if (PyString_Check(in)) {
1464 *out = PyString_AsString(in);
1465 return 1;
1466 }
1467 if (PyTclObject_Check(in)) {
1468 *out = PyTclObject_TclString(in);
1469 return 1;
1470 }
1471 /* XXX: Should give diagnostics. */
1472 return 0;
1473}
1474
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001475void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001476var_perform(VarEvent *ev)
1477{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001478 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1479 if (!*(ev->res)) {
1480 PyObject *exc, *val, *tb;
1481 PyErr_Fetch(&exc, &val, &tb);
1482 PyErr_NormalizeException(&exc, &val, &tb);
1483 *(ev->exc_type) = exc;
1484 *(ev->exc_val) = val;
1485 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001487
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001488}
1489
1490static int
1491var_proc(VarEvent* ev, int flags)
1492{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001493 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001494 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001495 Tcl_MutexLock(&var_mutex);
1496 Tcl_ConditionNotify(&ev->cond);
1497 Tcl_MutexUnlock(&var_mutex);
1498 LEAVE_PYTHON
1499 return 1;
1500}
1501
1502static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001503var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001504{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001505 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001506#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001507 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001508 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001509 VarEvent *ev;
1510 PyObject *res, *exc_type, *exc_val;
1511
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001512 /* The current thread is not the interpreter thread. Marshal
1513 the call to the interpreter thread, then wait for
1514 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001515 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001516 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001517
1518 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1519
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001520 ev->self = selfptr;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001521 ev->args = args;
1522 ev->flags = flags;
1523 ev->func = func;
1524 ev->res = &res;
1525 ev->exc_type = &exc_type;
1526 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001527 ev->cond = NULL;
1528 ev->ev.proc = (Tcl_EventProc*)var_proc;
1529 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001530 if (!res) {
1531 PyErr_SetObject(exc_type, exc_val);
1532 Py_DECREF(exc_type);
1533 Py_DECREF(exc_val);
1534 return NULL;
1535 }
1536 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001537 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001538#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001539 /* Tcl is not threaded, or this is the interpreter thread. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001540 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001541}
1542
Guido van Rossum18468821994-06-20 07:49:28 +00001543static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001544SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001545{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001546 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001547 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001548 PyObject *res = NULL;
1549 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001550
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001551 if (PyArg_ParseTuple(args, "O&O:setvar",
1552 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001553 /* XXX Acquire tcl lock??? */
1554 newval = AsObj(newValue);
1555 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001556 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001557 ENTER_TCL
1558 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1559 newval, flags);
1560 ENTER_OVERLAP
1561 if (!ok)
1562 Tkinter_Error(self);
1563 else {
1564 res = Py_None;
1565 Py_INCREF(res);
1566 }
1567 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001568 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001569 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001570 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001571 if (PyArg_ParseTuple(args, "ssO:setvar",
1572 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001573 /* XXX must hold tcl lock already??? */
1574 newval = AsObj(newValue);
1575 ENTER_TCL
1576 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1577 ENTER_OVERLAP
1578 if (!ok)
1579 Tkinter_Error(self);
1580 else {
1581 res = Py_None;
1582 Py_INCREF(res);
1583 }
1584 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001585 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001586 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001587 return NULL;
1588 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001589 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001590 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001591}
1592
1593static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001594Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001595{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001596 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001597}
1598
1599static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001600Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001601{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001602 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001603}
1604
Barry Warsawfa701a81997-01-16 00:15:11 +00001605
1606
Guido van Rossum18468821994-06-20 07:49:28 +00001607static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001608GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001609{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001610 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001611 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001612 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001613
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001614 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1615 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001616 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001617
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001618 ENTER_TCL
1619 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1620 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001621 if (tres == NULL) {
1622 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1623 } else {
1624 if (((TkappObject*)self)->wantobjects) {
1625 res = FromObj(self, tres);
1626 }
1627 else {
1628 res = PyString_FromString(Tcl_GetString(tres));
1629 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001630 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001631 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001632 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001633}
1634
1635static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001636Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001637{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001638 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001639}
1640
1641static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001642Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001643{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001644 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001645}
1646
Barry Warsawfa701a81997-01-16 00:15:11 +00001647
1648
Guido van Rossum18468821994-06-20 07:49:28 +00001649static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001650UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001651{
Guido van Rossum35d43371997-08-02 00:09:09 +00001652 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001653 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001654 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001655
Guido van Rossum43713e52000-02-29 13:59:29 +00001656 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001657 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001658
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001659 ENTER_TCL
1660 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1661 ENTER_OVERLAP
1662 if (code == TCL_ERROR)
1663 res = Tkinter_Error(self);
1664 else {
1665 Py_INCREF(Py_None);
1666 res = Py_None;
1667 }
1668 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001669 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001670}
1671
1672static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001673Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001674{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001675 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001676}
1677
1678static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001679Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001680{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001681 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001682}
1683
Barry Warsawfa701a81997-01-16 00:15:11 +00001684
1685
Guido van Rossum18468821994-06-20 07:49:28 +00001686/** Tcl to Python **/
1687
1688static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001689Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001690{
Barry Warsawfa701a81997-01-16 00:15:11 +00001691 char *s;
1692 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001693
Martin v. Löwisffad6332002-11-26 09:28:05 +00001694 if (PyTuple_Size(args) == 1) {
1695 PyObject* o = PyTuple_GetItem(args, 0);
1696 if (PyInt_Check(o)) {
1697 Py_INCREF(o);
1698 return o;
1699 }
1700 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001701 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001702 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001703 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001704 return Tkinter_Error(self);
1705 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001706}
1707
1708static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001709Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001710{
Barry Warsawfa701a81997-01-16 00:15:11 +00001711 char *s;
1712 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001713
Martin v. Löwisffad6332002-11-26 09:28:05 +00001714 if (PyTuple_Size(args) == 1) {
1715 PyObject *o = PyTuple_GetItem(args, 0);
1716 if (PyFloat_Check(o)) {
1717 Py_INCREF(o);
1718 return o;
1719 }
1720 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001721 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001722 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001723 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001724 return Tkinter_Error(self);
1725 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001726}
1727
1728static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001729Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001730{
Barry Warsawfa701a81997-01-16 00:15:11 +00001731 char *s;
1732 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001733
Martin v. Löwisffad6332002-11-26 09:28:05 +00001734 if (PyTuple_Size(args) == 1) {
1735 PyObject *o = PyTuple_GetItem(args, 0);
1736 if (PyInt_Check(o)) {
1737 Py_INCREF(o);
1738 return o;
1739 }
1740 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001741 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001742 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001743 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1744 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001745 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001746}
1747
1748static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001749Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001750{
Barry Warsawfa701a81997-01-16 00:15:11 +00001751 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001752 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001753 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001754
Guido van Rossum43713e52000-02-29 13:59:29 +00001755 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001756 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001757
1758 CHECK_TCL_APPARTMENT;
1759
Guido van Rossum00d93061998-05-28 23:06:38 +00001760 ENTER_TCL
1761 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001762 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001763 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001764 res = Tkinter_Error(self);
1765 else
1766 res = Py_BuildValue("s", Tkapp_Result(self));
1767 LEAVE_OVERLAP_TCL
1768 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001769}
1770
1771static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001772Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001773{
Barry Warsawfa701a81997-01-16 00:15:11 +00001774 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001775 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001776 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001777 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001778
Guido van Rossum43713e52000-02-29 13:59:29 +00001779 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001780 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001781
1782 CHECK_TCL_APPARTMENT;
1783
Guido van Rossum00d93061998-05-28 23:06:38 +00001784 ENTER_TCL
1785 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001786 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001787 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001788 res = Tkinter_Error(self);
1789 else
1790 res = Py_BuildValue("l", v);
1791 LEAVE_OVERLAP_TCL
1792 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001793}
1794
1795static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001796Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001797{
Barry Warsawfa701a81997-01-16 00:15:11 +00001798 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001799 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001800 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001801 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001802
Guido van Rossum43713e52000-02-29 13:59:29 +00001803 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001804 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001805 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001806 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001807 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001808 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001809 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001810 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001811 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001812 res = Tkinter_Error(self);
1813 else
1814 res = Py_BuildValue("d", v);
1815 LEAVE_OVERLAP_TCL
1816 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001817}
1818
1819static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001820Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001821{
Barry Warsawfa701a81997-01-16 00:15:11 +00001822 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001823 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001824 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001825 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001826
Guido van Rossum43713e52000-02-29 13:59:29 +00001827 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001828 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001829 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001830 ENTER_TCL
1831 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001832 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001833 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001834 res = Tkinter_Error(self);
1835 else
1836 res = Py_BuildValue("i", v);
1837 LEAVE_OVERLAP_TCL
1838 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001839}
1840
Barry Warsawfa701a81997-01-16 00:15:11 +00001841
1842
Guido van Rossum18468821994-06-20 07:49:28 +00001843static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001844Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001845{
Barry Warsawfa701a81997-01-16 00:15:11 +00001846 char *list;
1847 int argc;
1848 char **argv;
1849 PyObject *v;
1850 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001851
Martin v. Löwisffad6332002-11-26 09:28:05 +00001852 if (PyTuple_Size(args) == 1) {
1853 v = PyTuple_GetItem(args, 0);
1854 if (PyTuple_Check(v)) {
1855 Py_INCREF(v);
1856 return v;
1857 }
1858 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001859 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001860 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001861
Neal Norwitzd1c55102003-05-29 00:17:03 +00001862 if (Tcl_SplitList(Tkapp_Interp(self), list,
1863 &argc, &argv) == TCL_ERROR) {
1864 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001865 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001866 }
Guido van Rossum18468821994-06-20 07:49:28 +00001867
Barry Warsawfa701a81997-01-16 00:15:11 +00001868 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001869 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001870
Barry Warsawfa701a81997-01-16 00:15:11 +00001871 for (i = 0; i < argc; i++) {
1872 PyObject *s = PyString_FromString(argv[i]);
1873 if (!s || PyTuple_SetItem(v, i, s)) {
1874 Py_DECREF(v);
1875 v = NULL;
1876 goto finally;
1877 }
1878 }
Guido van Rossum18468821994-06-20 07:49:28 +00001879
Barry Warsawfa701a81997-01-16 00:15:11 +00001880 finally:
1881 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001882 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001883 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001884}
1885
1886static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001887Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001888{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001889 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001890 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001891
Martin v. Löwisffad6332002-11-26 09:28:05 +00001892 if (PyTuple_Size(args) == 1) {
1893 PyObject* o = PyTuple_GetItem(args, 0);
1894 if (PyTuple_Check(o)) {
1895 o = SplitObj(o);
1896 return o;
1897 }
1898 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001899 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001900 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001901 v = Split(list);
1902 PyMem_Free(list);
1903 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001904}
1905
1906static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001907Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001908{
Barry Warsawfa701a81997-01-16 00:15:11 +00001909 char *s = Merge(args);
1910 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001911
Barry Warsawfa701a81997-01-16 00:15:11 +00001912 if (s) {
1913 res = PyString_FromString(s);
1914 ckfree(s);
1915 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001916
1917 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001918}
1919
Barry Warsawfa701a81997-01-16 00:15:11 +00001920
1921
Guido van Rossum18468821994-06-20 07:49:28 +00001922/** Tcl Command **/
1923
Guido van Rossum00d93061998-05-28 23:06:38 +00001924/* Client data struct */
1925typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001926 PyObject *self;
1927 PyObject *func;
1928} PythonCmd_ClientData;
1929
1930static int
Fred Drake509d79a2000-07-08 04:04:38 +00001931PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001932{
1933 errorInCmd = 1;
1934 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1935 LEAVE_PYTHON
1936 return TCL_ERROR;
1937}
1938
Guido van Rossum18468821994-06-20 07:49:28 +00001939/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001940 * function or method.
1941 */
Guido van Rossum18468821994-06-20 07:49:28 +00001942static int
Fred Drake509d79a2000-07-08 04:04:38 +00001943PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001944{
Guido van Rossum00d93061998-05-28 23:06:38 +00001945 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001946 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001947 int i, rv;
1948 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001949
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001950 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001951
Barry Warsawfa701a81997-01-16 00:15:11 +00001952 /* TBD: no error checking here since we know, via the
1953 * Tkapp_CreateCommand() that the client data is a two-tuple
1954 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001955 self = data->self;
1956 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001957
Barry Warsawfa701a81997-01-16 00:15:11 +00001958 /* Create argument list (argv1, ..., argvN) */
1959 if (!(arg = PyTuple_New(argc - 1)))
1960 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001961
Barry Warsawfa701a81997-01-16 00:15:11 +00001962 for (i = 0; i < (argc - 1); i++) {
1963 PyObject *s = PyString_FromString(argv[i + 1]);
1964 if (!s || PyTuple_SetItem(arg, i, s)) {
1965 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001966 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001967 }
1968 }
1969 res = PyEval_CallObject(func, arg);
1970 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001971
Barry Warsawfa701a81997-01-16 00:15:11 +00001972 if (res == NULL)
1973 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001974
Barry Warsawfa701a81997-01-16 00:15:11 +00001975 if (!(tmp = PyList_New(0))) {
1976 Py_DECREF(res);
1977 return PythonCmd_Error(interp);
1978 }
1979
Guido van Rossum2834b972000-10-06 16:58:26 +00001980 s = AsString(res, tmp);
1981 if (s == NULL) {
1982 rv = PythonCmd_Error(interp);
1983 }
1984 else {
1985 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1986 rv = TCL_OK;
1987 }
1988
Barry Warsawfa701a81997-01-16 00:15:11 +00001989 Py_DECREF(res);
1990 Py_DECREF(tmp);
1991
Guido van Rossum00d93061998-05-28 23:06:38 +00001992 LEAVE_PYTHON
1993
Guido van Rossum2834b972000-10-06 16:58:26 +00001994 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001995}
1996
1997static void
Fred Drake509d79a2000-07-08 04:04:38 +00001998PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001999{
Guido van Rossum00d93061998-05-28 23:06:38 +00002000 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2001
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002002 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002003 Py_XDECREF(data->self);
2004 Py_XDECREF(data->func);
2005 PyMem_DEL(data);
2006 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002007}
2008
Barry Warsawfa701a81997-01-16 00:15:11 +00002009
2010
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002011
2012TCL_DECLARE_MUTEX(command_mutex)
2013
2014typedef struct CommandEvent{
2015 Tcl_Event ev;
2016 Tcl_Interp* interp;
2017 char *name;
2018 int create;
2019 int *status;
2020 ClientData *data;
2021 Tcl_Condition done;
2022} CommandEvent;
2023
2024static int
2025Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002026{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002027 if (ev->create)
2028 *ev->status = Tcl_CreateCommand(
2029 ev->interp, ev->name, PythonCmd,
2030 ev->data, PythonCmdDelete) == NULL;
2031 else
2032 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2033 Tcl_MutexLock(&command_mutex);
2034 Tcl_ConditionNotify(&ev->done);
2035 Tcl_MutexUnlock(&command_mutex);
2036 return 1;
2037}
2038
2039static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002040Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002041{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002042 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002043 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002044 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002045 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002046 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002047
Guido van Rossum43713e52000-02-29 13:59:29 +00002048 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002049 return NULL;
2050 if (!PyCallable_Check(func)) {
2051 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002052 return NULL;
2053 }
Guido van Rossum18468821994-06-20 07:49:28 +00002054
Martin v. Löwisa9656492003-03-30 08:44:58 +00002055#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002056 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002057 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002058 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002059#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002060
Guido van Rossum00d93061998-05-28 23:06:38 +00002061 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002062 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002063 return PyErr_NoMemory();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002064 Py_INCREF(self);
2065 Py_INCREF(func);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002066 data->self = selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002067 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002068
2069 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2070 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2071 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2072 ev->interp = self->interp;
2073 ev->create = 1;
2074 ev->name = cmdName;
2075 ev->data = (ClientData)data;
2076 ev->status = &err;
2077 ev->done = NULL;
2078 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2079 }
2080 else {
2081 ENTER_TCL
2082 err = Tcl_CreateCommand(
2083 Tkapp_Interp(self), cmdName, PythonCmd,
2084 (ClientData)data, PythonCmdDelete) == NULL;
2085 LEAVE_TCL
2086 }
2087 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002088 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002089 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002090 return NULL;
2091 }
Guido van Rossum18468821994-06-20 07:49:28 +00002092
Barry Warsawfa701a81997-01-16 00:15:11 +00002093 Py_INCREF(Py_None);
2094 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002095}
2096
Barry Warsawfa701a81997-01-16 00:15:11 +00002097
2098
Guido van Rossum18468821994-06-20 07:49:28 +00002099static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002100Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002101{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002102 TkappObject *self = (TkappObject*)selfptr;
Barry Warsawfa701a81997-01-16 00:15:11 +00002103 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002104 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002105
Guido van Rossum43713e52000-02-29 13:59:29 +00002106 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002107 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002108 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2109 CommandEvent *ev;
2110 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2111 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2112 ev->interp = self->interp;
2113 ev->create = 0;
2114 ev->name = cmdName;
2115 ev->status = &err;
2116 ev->done = NULL;
2117 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2118 &command_mutex);
2119 }
2120 else {
2121 ENTER_TCL
2122 err = Tcl_DeleteCommand(self->interp, cmdName);
2123 LEAVE_TCL
2124 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002125 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002126 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2127 return NULL;
2128 }
2129 Py_INCREF(Py_None);
2130 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002131}
2132
Barry Warsawfa701a81997-01-16 00:15:11 +00002133
2134
Guido van Rossum00d93061998-05-28 23:06:38 +00002135#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002136/** File Handler **/
2137
Guido van Rossum00d93061998-05-28 23:06:38 +00002138typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002139 PyObject *func;
2140 PyObject *file;
2141 int id;
2142 struct _fhcdata *next;
2143} FileHandler_ClientData;
2144
2145static FileHandler_ClientData *HeadFHCD;
2146
2147static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002148NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002149{
2150 FileHandler_ClientData *p;
2151 p = PyMem_NEW(FileHandler_ClientData, 1);
2152 if (p != NULL) {
2153 Py_XINCREF(func);
2154 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002155 p->func = func;
2156 p->file = file;
2157 p->id = id;
2158 p->next = HeadFHCD;
2159 HeadFHCD = p;
2160 }
2161 return p;
2162}
2163
2164static void
Fred Drake509d79a2000-07-08 04:04:38 +00002165DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002166{
2167 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002168
2169 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002170 while ((p = *pp) != NULL) {
2171 if (p->id == id) {
2172 *pp = p->next;
2173 Py_XDECREF(p->func);
2174 Py_XDECREF(p->file);
2175 PyMem_DEL(p);
2176 }
2177 else
2178 pp = &p->next;
2179 }
2180}
2181
Guido van Rossuma597dde1995-01-10 20:56:29 +00002182static void
Fred Drake509d79a2000-07-08 04:04:38 +00002183FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002184{
Guido van Rossum00d93061998-05-28 23:06:38 +00002185 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002186 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002187
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002188 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002189 func = data->func;
2190 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002191
Barry Warsawfa701a81997-01-16 00:15:11 +00002192 arg = Py_BuildValue("(Oi)", file, (long) mask);
2193 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002194 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002195
2196 if (res == NULL) {
2197 errorInCmd = 1;
2198 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2199 }
2200 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002201 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002202}
2203
Guido van Rossum18468821994-06-20 07:49:28 +00002204static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002205Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2206 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002207{
Guido van Rossum00d93061998-05-28 23:06:38 +00002208 FileHandler_ClientData *data;
2209 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002210 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002211
Guido van Rossum2834b972000-10-06 16:58:26 +00002212 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2213 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002214 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002215
Martin v. Löwisa9656492003-03-30 08:44:58 +00002216#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002217 if (!self && !tcl_lock) {
2218 /* We don't have the Tcl lock since Tcl is threaded. */
2219 PyErr_SetString(PyExc_RuntimeError,
2220 "_tkinter.createfilehandler not supported "
2221 "for threaded Tcl");
2222 return NULL;
2223 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002224#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002225
2226 if (self) {
2227 CHECK_TCL_APPARTMENT;
2228 }
2229
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002230 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002231 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002232 return NULL;
2233 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002234 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002235 return NULL;
2236 }
2237
Guido van Rossuma80649b2000-03-28 20:07:05 +00002238 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002239 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002240 return NULL;
2241
Barry Warsawfa701a81997-01-16 00:15:11 +00002242 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002243 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002244 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002245 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002246 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002247 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002248}
2249
2250static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002251Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002252{
Barry Warsawfa701a81997-01-16 00:15:11 +00002253 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002254 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002255
Guido van Rossum43713e52000-02-29 13:59:29 +00002256 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002257 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002258
Martin v. Löwisa9656492003-03-30 08:44:58 +00002259#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002260 if (!self && !tcl_lock) {
2261 /* We don't have the Tcl lock since Tcl is threaded. */
2262 PyErr_SetString(PyExc_RuntimeError,
2263 "_tkinter.deletefilehandler not supported "
2264 "for threaded Tcl");
2265 return NULL;
2266 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002267#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002268
2269 if (self) {
2270 CHECK_TCL_APPARTMENT;
2271 }
2272
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002273 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002274 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002275 return NULL;
2276
Guido van Rossuma80649b2000-03-28 20:07:05 +00002277 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002278
Barry Warsawfa701a81997-01-16 00:15:11 +00002279 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002280 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002281 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002282 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002283 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002284 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002285}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002286#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002287
Barry Warsawfa701a81997-01-16 00:15:11 +00002288
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002289/**** Tktt Object (timer token) ****/
2290
Jeremy Hylton938ace62002-07-17 16:30:39 +00002291static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002292
Guido van Rossum00d93061998-05-28 23:06:38 +00002293typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002294 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002295 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002296 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002297} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002298
2299static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002300Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002301{
Barry Warsawfa701a81997-01-16 00:15:11 +00002302 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002303 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002304
Guido van Rossum43713e52000-02-29 13:59:29 +00002305 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002306 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002307 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002308 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002309 v->token = NULL;
2310 }
2311 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002312 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002313 Py_DECREF(func);
2314 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002315 }
2316 Py_INCREF(Py_None);
2317 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002318}
2319
2320static PyMethodDef Tktt_methods[] =
2321{
Neal Norwitzb0493252002-03-31 14:44:22 +00002322 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002323 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002324};
2325
2326static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002327Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002328{
Barry Warsawfa701a81997-01-16 00:15:11 +00002329 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002330
Guido van Rossumb18618d2000-05-03 23:44:39 +00002331 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002332 if (v == NULL)
2333 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002334
Guido van Rossum00d93061998-05-28 23:06:38 +00002335 Py_INCREF(func);
2336 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002337 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002338
2339 /* Extra reference, deleted when called or when handler is deleted */
2340 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002341 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002342}
2343
2344static void
Fred Drake509d79a2000-07-08 04:04:38 +00002345Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002346{
Guido van Rossum00d93061998-05-28 23:06:38 +00002347 TkttObject *v = (TkttObject *)self;
2348 PyObject *func = v->func;
2349
2350 Py_XDECREF(func);
2351
Guido van Rossumb18618d2000-05-03 23:44:39 +00002352 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002353}
2354
Guido van Rossum597ac201998-05-12 14:36:19 +00002355static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002356Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002357{
Barry Warsawfa701a81997-01-16 00:15:11 +00002358 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002359 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002360
Tim Peters885d4572001-11-28 20:27:42 +00002361 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002362 v->func == NULL ? ", handler deleted" : "");
Walter Dörwald1ab83302007-05-18 17:15:44 +00002363 return PyUnicode_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002364}
2365
2366static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002367Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002368{
Barry Warsawfa701a81997-01-16 00:15:11 +00002369 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002370}
2371
2372static PyTypeObject Tktt_Type =
2373{
Guido van Rossum35d43371997-08-02 00:09:09 +00002374 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002375 0, /*ob_size */
2376 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002377 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002378 0, /*tp_itemsize */
2379 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002380 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002381 Tktt_GetAttr, /*tp_getattr */
2382 0, /*tp_setattr */
2383 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002384 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002385 0, /*tp_as_number */
2386 0, /*tp_as_sequence */
2387 0, /*tp_as_mapping */
2388 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002389};
2390
Barry Warsawfa701a81997-01-16 00:15:11 +00002391
2392
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002393/** Timer Handler **/
2394
2395static void
Fred Drake509d79a2000-07-08 04:04:38 +00002396TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002397{
Guido van Rossum00d93061998-05-28 23:06:38 +00002398 TkttObject *v = (TkttObject *)clientData;
2399 PyObject *func = v->func;
2400 PyObject *res;
2401
2402 if (func == NULL)
2403 return;
2404
2405 v->func = NULL;
2406
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002407 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002408
2409 res = PyEval_CallObject(func, NULL);
2410 Py_DECREF(func);
2411 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002412
Barry Warsawfa701a81997-01-16 00:15:11 +00002413 if (res == NULL) {
2414 errorInCmd = 1;
2415 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2416 }
2417 else
2418 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002419
2420 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002421}
2422
2423static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002424Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002425{
Barry Warsawfa701a81997-01-16 00:15:11 +00002426 int milliseconds;
2427 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002428 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002429
Guido van Rossum2834b972000-10-06 16:58:26 +00002430 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2431 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002432 return NULL;
2433 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002434 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002435 return NULL;
2436 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002437
Martin v. Löwisa9656492003-03-30 08:44:58 +00002438#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002439 if (!self && !tcl_lock) {
2440 /* We don't have the Tcl lock since Tcl is threaded. */
2441 PyErr_SetString(PyExc_RuntimeError,
2442 "_tkinter.createtimerhandler not supported "
2443 "for threaded Tcl");
2444 return NULL;
2445 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002446#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002447
2448 if (self) {
2449 CHECK_TCL_APPARTMENT;
2450 }
2451
Guido van Rossum00d93061998-05-28 23:06:38 +00002452 v = Tktt_New(func);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002453 if (v) {
2454 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2455 (ClientData)v);
2456 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002457
Guido van Rossum00d93061998-05-28 23:06:38 +00002458 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002459}
2460
Barry Warsawfa701a81997-01-16 00:15:11 +00002461
Guido van Rossum18468821994-06-20 07:49:28 +00002462/** Event Loop **/
2463
Guido van Rossum18468821994-06-20 07:49:28 +00002464static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002465Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002466{
Barry Warsawfa701a81997-01-16 00:15:11 +00002467 int threshold = 0;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002468 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002469#ifdef WITH_THREAD
2470 PyThreadState *tstate = PyThreadState_Get();
2471#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002472
Guido van Rossum43713e52000-02-29 13:59:29 +00002473 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002474 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002475
Martin v. Löwisa9656492003-03-30 08:44:58 +00002476#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002477 if (!self && !tcl_lock) {
2478 /* We don't have the Tcl lock since Tcl is threaded. */
2479 PyErr_SetString(PyExc_RuntimeError,
2480 "_tkinter.mainloop not supported "
2481 "for threaded Tcl");
2482 return NULL;
2483 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002484#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002485
2486 if (self) {
2487 CHECK_TCL_APPARTMENT;
2488 self->dispatching = 1;
2489 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002490
Barry Warsawfa701a81997-01-16 00:15:11 +00002491 quitMainLoop = 0;
2492 while (Tk_GetNumMainWindows() > threshold &&
2493 !quitMainLoop &&
2494 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002495 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002496 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002497
2498#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002499 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002500 /* Allow other Python threads to run. */
2501 ENTER_TCL
2502 result = Tcl_DoOneEvent(0);
2503 LEAVE_TCL
2504 }
2505 else {
2506 Py_BEGIN_ALLOW_THREADS
2507 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2508 tcl_tstate = tstate;
2509 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2510 tcl_tstate = NULL;
2511 if(tcl_lock)PyThread_release_lock(tcl_lock);
2512 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002513 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002514 Py_END_ALLOW_THREADS
2515 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002516#else
2517 result = Tcl_DoOneEvent(0);
2518#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002519
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002520 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002521 if (self)
2522 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002523 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002524 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002525 if (result < 0)
2526 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002527 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002528 if (self)
2529 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002530 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002531
Barry Warsawfa701a81997-01-16 00:15:11 +00002532 if (errorInCmd) {
2533 errorInCmd = 0;
2534 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2535 excInCmd = valInCmd = trbInCmd = NULL;
2536 return NULL;
2537 }
2538 Py_INCREF(Py_None);
2539 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002540}
2541
2542static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002543Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002544{
Guido van Rossum35d43371997-08-02 00:09:09 +00002545 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002546 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002547
Guido van Rossum43713e52000-02-29 13:59:29 +00002548 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002549 return NULL;
2550
Guido van Rossum00d93061998-05-28 23:06:38 +00002551 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002552 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002553 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002554 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002555}
2556
2557static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002558Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002559{
2560
Guido van Rossum43713e52000-02-29 13:59:29 +00002561 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002562 return NULL;
2563
2564 quitMainLoop = 1;
2565 Py_INCREF(Py_None);
2566 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002567}
2568
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002569static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002570Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002571{
2572
Guido van Rossum43713e52000-02-29 13:59:29 +00002573 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002574 return NULL;
2575
2576 return PyInt_FromLong((long)Tkapp_Interp(self));
2577}
2578
David Aschere2b4b322004-02-18 05:59:53 +00002579static PyObject *
2580Tkapp_TkInit(PyObject *self, PyObject *args)
2581{
Thomas Wouters477c8d52006-05-27 19:21:47 +00002582 static int has_failed;
David Aschere2b4b322004-02-18 05:59:53 +00002583 Tcl_Interp *interp = Tkapp_Interp(self);
Neal Norwitz44dbae82004-02-19 02:44:22 +00002584 Tk_Window main_window;
David Aschere2b4b322004-02-18 05:59:53 +00002585 const char * _tk_exists = NULL;
David Aschere2b4b322004-02-18 05:59:53 +00002586 int err;
Neal Norwitz44dbae82004-02-19 02:44:22 +00002587 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002588
Thomas Wouters477c8d52006-05-27 19:21:47 +00002589 /* In all current versions of Tk (including 8.4.13), Tk_Init
2590 deadlocks on the second call when the first call failed.
2591 To avoid the deadlock, we just refuse the second call through
2592 a static variable. */
2593 if (has_failed) {
2594 PyErr_SetString(Tkinter_TclError,
2595 "Calling Tk_Init again after a previous call failed might deadlock");
2596 return NULL;
2597 }
2598
David Aschere2b4b322004-02-18 05:59:53 +00002599 /* We want to guard against calling Tk_Init() multiple times */
2600 CHECK_TCL_APPARTMENT;
2601 ENTER_TCL
2602 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2603 ENTER_OVERLAP
2604 if (err == TCL_ERROR) {
Thomas Wouters477c8d52006-05-27 19:21:47 +00002605 /* This sets an exception, but we cannot return right
2606 away because we need to exit the overlap first. */
2607 Tkinter_Error(self);
David Aschere2b4b322004-02-18 05:59:53 +00002608 } else {
2609 _tk_exists = Tkapp_Result(self);
2610 }
2611 LEAVE_OVERLAP_TCL
2612 if (err == TCL_ERROR) {
2613 return NULL;
2614 }
2615 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2616 if (Tk_Init(interp) == TCL_ERROR) {
2617 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Thomas Wouters477c8d52006-05-27 19:21:47 +00002618 has_failed = 1;
David Aschere2b4b322004-02-18 05:59:53 +00002619 return NULL;
2620 }
2621 }
2622 Py_INCREF(Py_None);
2623 return Py_None;
2624}
Barry Warsawfa701a81997-01-16 00:15:11 +00002625
Martin v. Löwisffad6332002-11-26 09:28:05 +00002626static PyObject *
2627Tkapp_WantObjects(PyObject *self, PyObject *args)
2628{
2629
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002630 int wantobjects = -1;
2631 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002632 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002633 if (wantobjects == -1)
2634 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002635 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002636
2637 Py_INCREF(Py_None);
2638 return Py_None;
2639}
2640
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002641static PyObject *
2642Tkapp_WillDispatch(PyObject *self, PyObject *args)
2643{
2644
2645 ((TkappObject*)self)->dispatching = 1;
2646
2647 Py_INCREF(Py_None);
2648 return Py_None;
2649}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002650
Barry Warsawfa701a81997-01-16 00:15:11 +00002651
Guido van Rossum18468821994-06-20 07:49:28 +00002652/**** Tkapp Method List ****/
2653
2654static PyMethodDef Tkapp_methods[] =
2655{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002656 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002657 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Guido van Rossumd59da4b2007-05-22 18:11:13 +00002658 {"call", Tkapp_Call, METH_VARARGS},
2659 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002660 {"eval", Tkapp_Eval, METH_VARARGS},
2661 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2662 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2663 {"record", Tkapp_Record, METH_VARARGS},
2664 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2665 {"setvar", Tkapp_SetVar, METH_VARARGS},
2666 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2667 {"getvar", Tkapp_GetVar, METH_VARARGS},
2668 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2669 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2670 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2671 {"getint", Tkapp_GetInt, METH_VARARGS},
2672 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2673 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2674 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2675 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2676 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2677 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2678 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2679 {"split", Tkapp_Split, METH_VARARGS},
Guido van Rossumd59da4b2007-05-22 18:11:13 +00002680 {"merge", Tkapp_Merge, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002681 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2682 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002683#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002684 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2685 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002686#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002687 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2688 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2689 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2690 {"quit", Tkapp_Quit, METH_VARARGS},
2691 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Neal Norwitz44dbae82004-02-19 02:44:22 +00002692 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002693 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002694};
2695
Barry Warsawfa701a81997-01-16 00:15:11 +00002696
2697
Guido van Rossum18468821994-06-20 07:49:28 +00002698/**** Tkapp Type Methods ****/
2699
2700static void
Fred Drake509d79a2000-07-08 04:04:38 +00002701Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002702{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002703 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002704 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002705 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002706 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002707 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002708 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002709}
2710
2711static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002712Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002713{
Guido van Rossum35d43371997-08-02 00:09:09 +00002714 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002715}
2716
2717static PyTypeObject Tkapp_Type =
2718{
Guido van Rossum35d43371997-08-02 00:09:09 +00002719 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002720 0, /*ob_size */
2721 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002722 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002723 0, /*tp_itemsize */
2724 Tkapp_Dealloc, /*tp_dealloc */
2725 0, /*tp_print */
2726 Tkapp_GetAttr, /*tp_getattr */
2727 0, /*tp_setattr */
2728 0, /*tp_compare */
2729 0, /*tp_repr */
2730 0, /*tp_as_number */
2731 0, /*tp_as_sequence */
2732 0, /*tp_as_mapping */
2733 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002734};
2735
Barry Warsawfa701a81997-01-16 00:15:11 +00002736
2737
Guido van Rossum18468821994-06-20 07:49:28 +00002738/**** Tkinter Module ****/
2739
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002740typedef struct {
2741 PyObject* tuple;
2742 int size; /* current size */
2743 int maxsize; /* allocated size */
2744} FlattenContext;
2745
2746static int
2747_bump(FlattenContext* context, int size)
2748{
Guido van Rossum2834b972000-10-06 16:58:26 +00002749 /* expand tuple to hold (at least) size new items.
2750 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002751
2752 int maxsize = context->maxsize * 2;
2753
2754 if (maxsize < context->size + size)
2755 maxsize = context->size + size;
2756
2757 context->maxsize = maxsize;
2758
Tim Peters4324aa32001-05-28 22:30:08 +00002759 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002760}
2761
2762static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002763_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002764{
2765 /* add tuple or list to argument tuple (recursively) */
2766
2767 int i, size;
2768
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002769 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002770 PyErr_SetString(PyExc_ValueError,
2771 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002772 return 0;
2773 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002774 size = PyList_GET_SIZE(item);
2775 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002776 if (context->size + size > context->maxsize &&
2777 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002778 return 0;
2779 /* copy items to output tuple */
2780 for (i = 0; i < size; i++) {
2781 PyObject *o = PyList_GET_ITEM(item, i);
2782 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002783 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002784 return 0;
2785 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002786 if (context->size + 1 > context->maxsize &&
2787 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002788 return 0;
2789 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002790 PyTuple_SET_ITEM(context->tuple,
2791 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002792 }
2793 }
2794 } else if (PyTuple_Check(item)) {
2795 /* same, for tuples */
2796 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002797 if (context->size + size > context->maxsize &&
2798 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002799 return 0;
2800 for (i = 0; i < size; i++) {
2801 PyObject *o = PyTuple_GET_ITEM(item, i);
2802 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002803 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002804 return 0;
2805 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002806 if (context->size + 1 > context->maxsize &&
2807 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002808 return 0;
2809 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002810 PyTuple_SET_ITEM(context->tuple,
2811 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002812 }
2813 }
2814 } else {
2815 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2816 return 0;
2817 }
2818 return 1;
2819}
2820
2821static PyObject *
2822Tkinter_Flatten(PyObject* self, PyObject* args)
2823{
2824 FlattenContext context;
2825 PyObject* item;
2826
2827 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2828 return NULL;
2829
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002830 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002831 if (context.maxsize <= 0)
2832 return PyTuple_New(0);
2833
2834 context.tuple = PyTuple_New(context.maxsize);
2835 if (!context.tuple)
2836 return NULL;
2837
2838 context.size = 0;
2839
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002840 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002841 return NULL;
2842
Tim Peters4324aa32001-05-28 22:30:08 +00002843 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002844 return NULL;
2845
2846 return context.tuple;
2847}
2848
Guido van Rossum18468821994-06-20 07:49:28 +00002849static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002850Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002851{
Barry Warsawfa701a81997-01-16 00:15:11 +00002852 char *screenName = NULL;
2853 char *baseName = NULL;
2854 char *className = NULL;
2855 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002856 int wantobjects = 0;
David Aschere2b4b322004-02-18 05:59:53 +00002857 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002858 int sync = 0; /* pass -sync to wish */
2859 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002860
Guido van Rossum35d43371997-08-02 00:09:09 +00002861 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002862 if (baseName != NULL)
2863 baseName++;
2864 else
2865 baseName = Py_GetProgramName();
2866 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002867
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002868 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002869 &screenName, &baseName, &className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002870 &interactive, &wantobjects, &wantTk,
2871 &sync, &use))
Barry Warsawfa701a81997-01-16 00:15:11 +00002872 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002873
Barry Warsawfa701a81997-01-16 00:15:11 +00002874 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002875 interactive, wantobjects, wantTk,
2876 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002877}
2878
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002879static PyObject *
2880Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2881{
2882 int new_val;
2883 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2884 return NULL;
2885 if (new_val < 0) {
2886 PyErr_SetString(PyExc_ValueError,
2887 "busywaitinterval must be >= 0");
2888 return NULL;
2889 }
2890 Tkinter_busywaitinterval = new_val;
2891 Py_INCREF(Py_None);
2892 return Py_None;
2893}
2894
2895static char setbusywaitinterval_doc[] =
2896"setbusywaitinterval(n) -> None\n\
2897\n\
2898Set the busy-wait interval in milliseconds between successive\n\
2899calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2900It should be set to a divisor of the maximum time between\n\
2901frames in an animation.";
2902
2903static PyObject *
2904Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2905{
2906 return PyInt_FromLong(Tkinter_busywaitinterval);
2907}
2908
2909static char getbusywaitinterval_doc[] =
2910"getbusywaitinterval() -> int\n\
2911\n\
2912Return the current busy-wait interval between successive\n\
2913calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2914
Guido van Rossum18468821994-06-20 07:49:28 +00002915static PyMethodDef moduleMethods[] =
2916{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002917 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2918 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002919#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002920 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2921 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002922#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002923 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2924 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2925 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2926 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002927 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2928 setbusywaitinterval_doc},
2929 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2930 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002931 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002932};
2933
Guido van Rossum7bf15641998-05-22 18:28:17 +00002934#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002935
2936static int stdin_ready = 0;
2937
Guido van Rossumad4db171998-06-13 13:56:28 +00002938#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002939static void
Fred Drake509d79a2000-07-08 04:04:38 +00002940MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002941{
2942 stdin_ready = 1;
2943}
Guido van Rossumad4db171998-06-13 13:56:28 +00002944#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002945
Martin v. Löwisa9656492003-03-30 08:44:58 +00002946#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002947static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002948#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002949
Guido van Rossum18468821994-06-20 07:49:28 +00002950static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002951EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002952{
Guido van Rossumad4db171998-06-13 13:56:28 +00002953#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002954 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002955#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002956#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002957 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002958#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002959 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002960 errorInCmd = 0;
2961#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002962 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002963 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002964#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002965 while (!errorInCmd && !stdin_ready) {
2966 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002967#ifdef MS_WINDOWS
2968 if (_kbhit()) {
2969 stdin_ready = 1;
2970 break;
2971 }
2972#endif
2973#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002974 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002975 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002976 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002977
Guido van Rossum00d93061998-05-28 23:06:38 +00002978 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002979
2980 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002981 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002982 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002983 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002984 Py_END_ALLOW_THREADS
2985#else
2986 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002987#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002988
2989 if (result < 0)
2990 break;
2991 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002992#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002993 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002994#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002995 if (errorInCmd) {
2996 errorInCmd = 0;
2997 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2998 excInCmd = valInCmd = trbInCmd = NULL;
2999 PyErr_Print();
3000 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003001#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00003002 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003003#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003004 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003005}
Guido van Rossum18468821994-06-20 07:49:28 +00003006
Guido van Rossum00d93061998-05-28 23:06:38 +00003007#endif
3008
Guido van Rossum7bf15641998-05-22 18:28:17 +00003009static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003010EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003011{
Guido van Rossum00d93061998-05-28 23:06:38 +00003012#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003013 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003014#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003015 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003016#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003017 PyOS_InputHook = EventHook;
3018 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003019#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003020}
3021
3022static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003023DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003024{
Guido van Rossum00d93061998-05-28 23:06:38 +00003025#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003026 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3027 PyOS_InputHook = NULL;
3028 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003029#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003030}
3031
Barry Warsawfa701a81997-01-16 00:15:11 +00003032
3033/* all errors will be checked in one fell swoop in init_tkinter() */
3034static void
Fred Drake509d79a2000-07-08 04:04:38 +00003035ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003036{
3037 PyObject *v = PyInt_FromLong(val);
3038 if (v) {
3039 PyDict_SetItemString(d, name, v);
3040 Py_DECREF(v);
3041 }
3042}
3043static void
Fred Drake509d79a2000-07-08 04:04:38 +00003044ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003045{
3046 PyObject *v = PyString_FromString(val);
3047 if (v) {
3048 PyDict_SetItemString(d, name, v);
3049 Py_DECREF(v);
3050 }
3051}
3052
3053
Mark Hammond62b1ab12002-07-23 06:31:15 +00003054PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003055init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003056{
Barry Warsawfa701a81997-01-16 00:15:11 +00003057 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003058
Barry Warsawfa701a81997-01-16 00:15:11 +00003059 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003060
3061#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003062 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003063#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003064
Barry Warsawfa701a81997-01-16 00:15:11 +00003065 m = Py_InitModule("_tkinter", moduleMethods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00003066 if (m == NULL)
3067 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003068
Barry Warsawfa701a81997-01-16 00:15:11 +00003069 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003070 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003071 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003072
Guido van Rossum35d43371997-08-02 00:09:09 +00003073 ins_long(d, "READABLE", TCL_READABLE);
3074 ins_long(d, "WRITABLE", TCL_WRITABLE);
3075 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3076 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3077 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3078 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3079 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3080 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3081 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003082 ins_string(d, "TK_VERSION", TK_VERSION);
3083 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003084
Guido van Rossum83551bf1997-09-13 00:44:23 +00003085 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003086
3087 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003088 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3089
Martin v. Löwisffad6332002-11-26 09:28:05 +00003090 PyTclObject_Type.ob_type = &PyType_Type;
3091 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003092
3093#ifdef TK_AQUA
3094 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3095 * start waking up. Note that Tcl_FindExecutable will do this, this
3096 * code must be above it! The original warning from
3097 * tkMacOSXAppInit.c is copied below.
3098 *
3099 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3100 * Tcl interpreter for now. It probably should work to do this
3101 * in the other order, but for now it doesn't seem to.
3102 *
3103 */
3104 Tk_MacOSXSetupTkNotifier();
3105#endif
3106
3107
Guido van Rossume187b0e2000-03-27 21:46:29 +00003108 /* This helps the dynamic loader; in Unicode aware Tcl versions
3109 it also helps Tcl find its encodings. */
3110 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003111
Barry Warsawfa701a81997-01-16 00:15:11 +00003112 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003113 return;
3114
Guido van Rossum43ff8681998-07-14 18:02:13 +00003115#if 0
3116 /* This was not a good idea; through <Destroy> bindings,
3117 Tcl_Finalize() may invoke Python code but at that point the
3118 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003119 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003120#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003121
Guido van Rossum18468821994-06-20 07:49:28 +00003122}