blob: c8e4ef72792a248d294d5d5e024dfac70d142e00 [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000012 Only Tcl/Tk 8.2 and later are supported. Older versions are not
13 supported. (Use Python 2.2 if you cannot upgrade your Tcl/Tk
Guido van Rossuma80649b2000-03-28 20:07:05 +000014 libraries.)
15*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Martin v. Löwis39195712003-01-04 00:33:13 +000036/* Allow using this code in Python 2.[12] */
37#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000038#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000039#endif
40
41#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000042#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000045#ifndef PyBool_Check
46#define PyBool_Check(o) 0
47#define PyBool_FromLong PyInt_FromLong
48#endif
49
Martin v. Löwis71e25a02002-10-01 18:08:06 +000050/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
51 making _tkinter correct for this API means to break earlier
52 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
53 earlier versions. Once Tcl releases before 8.4 don't need to be supported
54 anymore, this should go. */
55#define USE_COMPAT_CONST
56
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000057/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
58 it always; if Tcl is not threaded, the thread functions in
59 Tcl are empty. */
60#define TCL_THREADS
61
Jack Jansencb852442001-12-09 23:15:56 +000062#ifdef TK_FRAMEWORK
63#include <Tcl/tcl.h>
64#include <Tk/tk.h>
65#else
Guido van Rossum18468821994-06-20 07:49:28 +000066#include <tcl.h>
67#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000068#endif
Guido van Rossum18468821994-06-20 07:49:28 +000069
Jason Tishlerbbe89612002-12-31 20:30:46 +000070/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000071#ifndef CONST84_RETURN
72#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000073#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000074#define CONST
75#endif
76
Guido van Rossum3e819a71997-08-01 19:29:02 +000077#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
78
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000079#if TKMAJORMINOR < 8002
80#error "Tk older than 8.2 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000081#endif
82
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000083/* Unicode conversion assumes that Tcl_UniChar is two bytes.
84 We cannot test this directly, so we test UTF-8 size instead,
85 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000086 either UTF-16 or UCS-4.
87 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
88 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
89 as well.
90*/
91#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000092#error "unsupported Tcl configuration"
93#endif
94
Jack Janseneddc1442003-11-20 01:44:59 +000095#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000096#define HAVE_CREATEFILEHANDLER
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#ifdef HAVE_CREATEFILEHANDLER
100
Neal Norwitzd948a432006-01-08 01:08:55 +0000101/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
102 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
103#ifndef TCL_UNIX_FD
104# ifdef TCL_WIN_SOCKET
105# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
106# else
107# define TCL_UNIX_FD 1
108# endif
109#endif
110
Guido van Rossum00d93061998-05-28 23:06:38 +0000111/* Tcl_CreateFileHandler() changed several times; these macros deal with the
112 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
113 Unix, only because Jack added it back); when available on Windows, it only
114 applies to sockets. */
115
Guido van Rossum7bf15641998-05-22 18:28:17 +0000116#ifdef MS_WINDOWS
117#define FHANDLETYPE TCL_WIN_SOCKET
118#else
119#define FHANDLETYPE TCL_UNIX_FD
120#endif
121
Guido van Rossum00d93061998-05-28 23:06:38 +0000122/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
123 which uses this to handle Tcl events while the user is typing commands. */
124
125#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000126#define WAIT_FOR_STDIN
127#endif
128
Guido van Rossum00d93061998-05-28 23:06:38 +0000129#endif /* HAVE_CREATEFILEHANDLER */
130
Guido van Rossumad4db171998-06-13 13:56:28 +0000131#ifdef MS_WINDOWS
132#include <conio.h>
133#define WAIT_FOR_STDIN
134#endif
135
Guido van Rossum00d93061998-05-28 23:06:38 +0000136#ifdef WITH_THREAD
137
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000138/* The threading situation is complicated. Tcl is not thread-safe, except
139 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000140 So we need to use a lock around all uses of Tcl. Previously, the Python
141 interpreter lock was used for this. However, this causes problems when
142 other Python threads need to run while Tcl is blocked waiting for events.
143
144 To solve this problem, a separate lock for Tcl is introduced. Holding it
145 is incompatible with holding Python's interpreter lock. The following four
146 macros manipulate both locks together.
147
148 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
149 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
150 that could call an event handler, or otherwise affect the state of a Tcl
151 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000152 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000153 released and the lock for Tcl has been acquired.
154
Guido van Rossum5e977831998-06-15 14:03:52 +0000155 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
156 (For example, when transferring data from the Tcl interpreter result to a
157 Python string object.) This can be done by using different macros to close
158 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
159 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
160 releases the Tcl lock.
161
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000162 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000163 handlers when the handler needs to use Python. Such event handlers are
164 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000165 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000166 the Python interpreter lock, restoring the appropriate thread state, and
167 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
168 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000169 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000170
171 These locks expand to several statements and brackets; they should not be
172 used in branches of if statements and the like.
173
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000174 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
175 only valid in the thread that created it, and all Tk activity must happen in this
176 thread, also. That means that the mainloop must be invoked in the thread that
177 created the interpreter. Invoking commands from other threads is possible;
178 _tkinter will queue an event for the interpreter thread, which will then
179 execute the command and pass back the result. If the main thread is not in the
180 mainloop, and invoking commands causes an exception; if the main loop is running
181 but not processing events, the command invocation will block.
182
183 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
184 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
185 threads. So we use the Tcl TLS API.
186
Guido van Rossum00d93061998-05-28 23:06:38 +0000187*/
188
Guido van Rossum65d5b571998-12-21 19:32:43 +0000189static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000190
191#ifdef TCL_THREADS
192static Tcl_ThreadDataKey state_key;
193typedef PyThreadState *ThreadSpecificData;
194#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
195#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000196static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000197#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000198
199#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000200 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000201 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
203#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000204 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000205
Guido van Rossum62320c91998-06-15 04:36:09 +0000206#define ENTER_OVERLAP \
207 Py_END_ALLOW_THREADS
208
209#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000210 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000211
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000212#define ENTER_PYTHON \
213 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000214 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
216#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000217 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000218 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
219
220#define CHECK_TCL_APPARTMENT \
221 if (((TkappObject *)self)->threaded && \
222 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
223 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
224 return 0; \
225 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000226
227#else
228
229#define ENTER_TCL
230#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000231#define ENTER_OVERLAP
232#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000233#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000234#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000235#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000236
237#endif
238
Guido van Rossum97867b21996-08-08 19:09:53 +0000239#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000240#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000241#endif
242
Guido van Rossum18468821994-06-20 07:49:28 +0000243/**** Tkapp Object Declaration ****/
244
Jeremy Hylton938ace62002-07-17 16:30:39 +0000245static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000246
Guido van Rossum00d93061998-05-28 23:06:38 +0000247typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000248 PyObject_HEAD
249 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000250 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000251 int threaded; /* True if tcl_platform[threaded] */
252 Tcl_ThreadId thread_id;
253 int dispatching;
254 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000255 So we cache interesting types here. */
256 Tcl_ObjType *BooleanType;
257 Tcl_ObjType *ByteArrayType;
258 Tcl_ObjType *DoubleType;
259 Tcl_ObjType *IntType;
260 Tcl_ObjType *ListType;
261 Tcl_ObjType *ProcBodyType;
262 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000263} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000264
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000265#define Tkapp_Check(v) (Py_Type(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000266#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000267#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000268
Guido van Rossum35d43371997-08-02 00:09:09 +0000269#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000270(void *) v, Py_Refcnt(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000271
Barry Warsawfa701a81997-01-16 00:15:11 +0000272
273
Guido van Rossum18468821994-06-20 07:49:28 +0000274/**** Error Handling ****/
275
276static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000277static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000278static int errorInCmd = 0;
279static PyObject *excInCmd;
280static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000281static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
284
Guido van Rossum18468821994-06-20 07:49:28 +0000285static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000286Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000287{
Barry Warsawfa701a81997-01-16 00:15:11 +0000288 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
289 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000290}
291
Barry Warsawfa701a81997-01-16 00:15:11 +0000292
Barry Warsawfa701a81997-01-16 00:15:11 +0000293
Guido van Rossum18468821994-06-20 07:49:28 +0000294/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000295
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000296static int Tkinter_busywaitinterval = 20;
297
Guido van Rossum00d93061998-05-28 23:06:38 +0000298#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000299#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000300
Guido van Rossum00d93061998-05-28 23:06:38 +0000301/* Millisecond sleep() for Unix platforms. */
302
303static void
Fred Drake509d79a2000-07-08 04:04:38 +0000304Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000305{
306 /* XXX Too bad if you don't have select(). */
307 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000308 t.tv_sec = milli/1000;
309 t.tv_usec = (milli%1000) * 1000;
310 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
311}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000312#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000313
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000314/* Wait up to 1s for the mainloop to come up. */
315
316static int
317WaitForMainloop(TkappObject* self)
318{
319 int i;
320 for (i = 0; i < 10; i++) {
321 if (self->dispatching)
322 return 1;
323 Py_BEGIN_ALLOW_THREADS
324 Sleep(100);
325 Py_END_ALLOW_THREADS
326 }
327 if (self->dispatching)
328 return 1;
329 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
330 return 0;
331}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000332#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000333
Guido van Rossum00d93061998-05-28 23:06:38 +0000334
Guido van Rossum18468821994-06-20 07:49:28 +0000335static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000336AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000337{
Guido van Rossum35d43371997-08-02 00:09:09 +0000338 if (PyString_Check(value))
339 return PyString_AsString(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000340 else if (PyUnicode_Check(value)) {
341 PyObject *v = PyUnicode_AsUTF8String(value);
342 if (v == NULL)
343 return NULL;
344 if (PyList_Append(tmp, v) != 0) {
345 Py_DECREF(v);
346 return NULL;
347 }
348 Py_DECREF(v);
349 return PyString_AsString(v);
350 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000351 else {
352 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000353 if (v == NULL)
354 return NULL;
355 if (PyList_Append(tmp, v) != 0) {
356 Py_DECREF(v);
357 return NULL;
358 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000359 Py_DECREF(v);
360 return PyString_AsString(v);
361 }
Guido van Rossum18468821994-06-20 07:49:28 +0000362}
363
Barry Warsawfa701a81997-01-16 00:15:11 +0000364
365
Guido van Rossum18468821994-06-20 07:49:28 +0000366#define ARGSZ 64
367
368static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000369Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000370{
Barry Warsawfa701a81997-01-16 00:15:11 +0000371 PyObject *tmp = NULL;
372 char *argvStore[ARGSZ];
373 char **argv = NULL;
374 int fvStore[ARGSZ];
375 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000376 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000377 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000378
Barry Warsawfa701a81997-01-16 00:15:11 +0000379 if (!(tmp = PyList_New(0)))
380 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000381
Barry Warsawfa701a81997-01-16 00:15:11 +0000382 argv = argvStore;
383 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000384
Barry Warsawfa701a81997-01-16 00:15:11 +0000385 if (args == NULL)
386 argc = 0;
387
388 else if (!PyTuple_Check(args)) {
389 argc = 1;
390 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000391 if (!(argv[0] = AsString(args, tmp)))
392 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000393 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000394 else {
395 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000396
Barry Warsawfa701a81997-01-16 00:15:11 +0000397 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000398 argv = (char **)ckalloc(argc * sizeof(char *));
399 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000400 if (argv == NULL || fv == NULL) {
401 PyErr_NoMemory();
402 goto finally;
403 }
404 }
405
406 for (i = 0; i < argc; i++) {
407 PyObject *v = PyTuple_GetItem(args, i);
408 if (PyTuple_Check(v)) {
409 fv[i] = 1;
410 if (!(argv[i] = Merge(v)))
411 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000412 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000413 }
414 else if (v == Py_None) {
415 argc = i;
416 break;
417 }
418 else {
419 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000420 if (!(argv[i] = AsString(v, tmp)))
421 goto finally;
422 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000423 }
424 }
Guido van Rossum18468821994-06-20 07:49:28 +0000425 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000426 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000427 if (res == NULL)
428 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000429
Barry Warsawfa701a81997-01-16 00:15:11 +0000430 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000431 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000432 if (fv[i]) {
433 ckfree(argv[i]);
434 }
435 if (argv != argvStore)
436 ckfree(FREECAST argv);
437 if (fv != fvStore)
438 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000439
Barry Warsawfa701a81997-01-16 00:15:11 +0000440 Py_DECREF(tmp);
441 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000442}
443
Barry Warsawfa701a81997-01-16 00:15:11 +0000444
445
Guido van Rossum18468821994-06-20 07:49:28 +0000446static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000447Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000448{
Barry Warsawfa701a81997-01-16 00:15:11 +0000449 int argc;
450 char **argv;
451 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000452
Barry Warsawfa701a81997-01-16 00:15:11 +0000453 if (list == NULL) {
454 Py_INCREF(Py_None);
455 return Py_None;
456 }
Guido van Rossum18468821994-06-20 07:49:28 +0000457
Guido van Rossum00d93061998-05-28 23:06:38 +0000458 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000459 /* Not a list.
460 * Could be a quoted string containing funnies, e.g. {"}.
461 * Return the string itself.
462 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000463 return PyString_FromString(list);
464 }
Guido van Rossum18468821994-06-20 07:49:28 +0000465
Barry Warsawfa701a81997-01-16 00:15:11 +0000466 if (argc == 0)
467 v = PyString_FromString("");
468 else if (argc == 1)
469 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000470 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000471 int i;
472 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000473
Barry Warsawfa701a81997-01-16 00:15:11 +0000474 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000475 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000476 Py_DECREF(v);
477 v = NULL;
478 break;
479 }
480 PyTuple_SetItem(v, i, w);
481 }
482 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000483 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000484 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000485}
486
Martin v. Löwisffad6332002-11-26 09:28:05 +0000487/* In some cases, Tcl will still return strings that are supposed to be
488 lists. SplitObj walks through a nested tuple, finding string objects that
489 need to be split. */
490
491PyObject *
492SplitObj(PyObject *arg)
493{
494 if (PyTuple_Check(arg)) {
495 int i, size;
496 PyObject *elem, *newelem, *result;
497
498 size = PyTuple_Size(arg);
499 result = NULL;
500 /* Recursively invoke SplitObj for all tuple items.
501 If this does not return a new object, no action is
502 needed. */
503 for(i = 0; i < size; i++) {
504 elem = PyTuple_GetItem(arg, i);
505 newelem = SplitObj(elem);
506 if (!newelem) {
507 Py_XDECREF(result);
508 return NULL;
509 }
510 if (!result) {
511 int k;
512 if (newelem == elem) {
513 Py_DECREF(newelem);
514 continue;
515 }
516 result = PyTuple_New(size);
517 if (!result)
518 return NULL;
519 for(k = 0; k < i; k++) {
520 elem = PyTuple_GetItem(arg, k);
521 Py_INCREF(elem);
522 PyTuple_SetItem(result, k, elem);
523 }
524 }
525 PyTuple_SetItem(result, i, newelem);
526 }
527 if (result)
528 return result;
529 /* Fall through, returning arg. */
530 }
531 else if (PyString_Check(arg)) {
532 int argc;
533 char **argv;
534 char *list = PyString_AsString(arg);
535
536 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
537 Py_INCREF(arg);
538 return arg;
539 }
540 Tcl_Free(FREECAST argv);
541 if (argc > 1)
542 return Split(PyString_AsString(arg));
543 /* Fall through, returning arg. */
544 }
545 Py_INCREF(arg);
546 return arg;
547}
Barry Warsawfa701a81997-01-16 00:15:11 +0000548
549
Guido van Rossum18468821994-06-20 07:49:28 +0000550/**** Tkapp Object ****/
551
552#ifndef WITH_APPINIT
553int
Fred Drake509d79a2000-07-08 04:04:38 +0000554Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000555{
Barry Warsawfa701a81997-01-16 00:15:11 +0000556 Tk_Window main;
David Aschere2b4b322004-02-18 05:59:53 +0000557 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000558
Barry Warsawfa701a81997-01-16 00:15:11 +0000559 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000560 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000561 return TCL_ERROR;
562 }
David Aschere2b4b322004-02-18 05:59:53 +0000563 _tkinter_skip_tk_init = Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
564 if (_tkinter_skip_tk_init == NULL || strcmp(_tkinter_skip_tk_init, "1") != 0) {
565 main = Tk_MainWindow(interp);
566 if (Tk_Init(interp) == TCL_ERROR) {
567 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
568 return TCL_ERROR;
569 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000570 }
571 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000572}
573#endif /* !WITH_APPINIT */
574
Guido van Rossum18468821994-06-20 07:49:28 +0000575
Barry Warsawfa701a81997-01-16 00:15:11 +0000576
577
578/* Initialize the Tk application; see the `main' function in
579 * `tkMain.c'.
580 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000581
Thomas Wouters58d05102000-07-24 14:43:35 +0000582static void EnableEventHook(void); /* Forward */
583static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000584
Barry Warsawfa701a81997-01-16 00:15:11 +0000585static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000586Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000587 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000588{
589 TkappObject *v;
590 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000591
Guido van Rossumb18618d2000-05-03 23:44:39 +0000592 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000593 if (v == NULL)
594 return NULL;
595
596 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000597 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000598 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
599 TCL_GLOBAL_ONLY) != NULL;
600 v->thread_id = Tcl_GetCurrentThread();
601 v->dispatching = 0;
602
603#ifndef TCL_THREADS
604 if (v->threaded) {
605 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
606 Py_DECREF(v);
607 return 0;
608 }
609#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000610#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000611 if (v->threaded && tcl_lock) {
612 /* If Tcl is threaded, we don't need the lock. */
613 PyThread_free_lock(tcl_lock);
614 tcl_lock = NULL;
615 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000616#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000617
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000618 v->BooleanType = Tcl_GetObjType("boolean");
619 v->ByteArrayType = Tcl_GetObjType("bytearray");
620 v->DoubleType = Tcl_GetObjType("double");
621 v->IntType = Tcl_GetObjType("int");
622 v->ListType = Tcl_GetObjType("list");
623 v->ProcBodyType = Tcl_GetObjType("procbody");
624 v->StringType = Tcl_GetObjType("string");
625
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000626 /* Delete the 'exit' command, which can screw things up */
627 Tcl_DeleteCommand(v->interp, "exit");
628
Barry Warsawfa701a81997-01-16 00:15:11 +0000629 if (screenName != NULL)
630 Tcl_SetVar2(v->interp, "env", "DISPLAY",
631 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000632
Barry Warsawfa701a81997-01-16 00:15:11 +0000633 if (interactive)
634 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
635 else
636 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000637
Barry Warsawfa701a81997-01-16 00:15:11 +0000638 /* This is used to get the application class for Tk 4.1 and up */
639 argv0 = (char*)ckalloc(strlen(className) + 1);
640 if (!argv0) {
641 PyErr_NoMemory();
642 Py_DECREF(v);
643 return NULL;
644 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000645
Barry Warsawfa701a81997-01-16 00:15:11 +0000646 strcpy(argv0, className);
Neal Norwitz9dbc7dd2005-12-19 06:08:59 +0000647 if (isupper(Py_CHARMASK(argv0[0])))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000648 argv0[0] = tolower(Py_CHARMASK(argv0[0]));
Barry Warsawfa701a81997-01-16 00:15:11 +0000649 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
650 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000651
David Aschere2b4b322004-02-18 05:59:53 +0000652 if (! wantTk) {
653 Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
654 }
655
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000656 /* some initial arguments need to be in argv */
657 if (sync || use) {
Tim Peters51fa3b72004-08-04 02:16:48 +0000658 char *args;
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000659 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000660
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000661 if (sync)
662 len += sizeof "-sync";
663 if (use)
664 len += strlen(use) + sizeof "-use ";
665
Tim Peters51fa3b72004-08-04 02:16:48 +0000666 args = (char*)ckalloc(len);
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000667 if (!args) {
668 PyErr_NoMemory();
669 Py_DECREF(v);
670 return NULL;
671 }
672
673 args[0] = '\0';
674 if (sync)
675 strcat(args, "-sync");
676 if (use) {
677 if (sync)
678 strcat(args, " ");
679 strcat(args, "-use ");
680 strcat(args, use);
681 }
682
683 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
684 ckfree(args);
685 }
686
Thomas Woutersa74a84d2006-03-07 14:04:31 +0000687 if (Tcl_AppInit(v->interp) != TCL_OK) {
688 PyObject *result = Tkinter_Error((PyObject *)v);
689 Py_DECREF((PyObject *)v);
690 return (TkappObject *)result;
691 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000692
Guido van Rossum7bf15641998-05-22 18:28:17 +0000693 EnableEventHook();
694
Barry Warsawfa701a81997-01-16 00:15:11 +0000695 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000696}
697
Barry Warsawfa701a81997-01-16 00:15:11 +0000698
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000699static void
700Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
701 Tcl_Condition *cond, Tcl_Mutex *mutex)
702{
703 Py_BEGIN_ALLOW_THREADS;
704 Tcl_MutexLock(mutex);
705 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
706 Tcl_ThreadAlert(self->thread_id);
707 Tcl_ConditionWait(cond, mutex, NULL);
708 Tcl_MutexUnlock(mutex);
709 Py_END_ALLOW_THREADS
710}
711
Barry Warsawfa701a81997-01-16 00:15:11 +0000712
Guido van Rossum18468821994-06-20 07:49:28 +0000713/** Tcl Eval **/
714
Martin v. Löwisffad6332002-11-26 09:28:05 +0000715typedef struct {
716 PyObject_HEAD
717 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000718 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000719} PyTclObject;
720
Neal Norwitz227b5332006-03-22 09:28:35 +0000721static PyTypeObject PyTclObject_Type;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000722#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
723
724static PyObject *
725newPyTclObject(Tcl_Obj *arg)
726{
727 PyTclObject *self;
728 self = PyObject_New(PyTclObject, &PyTclObject_Type);
729 if (self == NULL)
730 return NULL;
731 Tcl_IncrRefCount(arg);
732 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000733 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000734 return (PyObject*)self;
735}
736
737static void
738PyTclObject_dealloc(PyTclObject *self)
739{
740 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000741 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000742 PyObject_Del(self);
743}
744
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000745static char*
746PyTclObject_TclString(PyObject *self)
747{
748 return Tcl_GetString(((PyTclObject*)self)->value);
749}
750
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000751/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000752PyDoc_STRVAR(PyTclObject_string__doc__,
Walter Dörwalda1884662007-07-12 12:16:02 +0000753"the string representation of this object, either as str8 or str");
Martin v. Löwis39195712003-01-04 00:33:13 +0000754
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000755static PyObject *
756PyTclObject_string(PyTclObject *self, void *ignored)
757{
758 char *s;
759 int i, len;
760 if (!self->string) {
761 s = Tcl_GetStringFromObj(self->value, &len);
762 for (i = 0; i < len; i++)
763 if (s[i] & 0x80)
764 break;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000765 if (i == len)
766 /* It is an ASCII string. */
767 self->string = PyString_FromStringAndSize(s, len);
768 else {
769 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
770 if (!self->string) {
771 PyErr_Clear();
772 self->string = PyString_FromStringAndSize(s, len);
773 }
774 }
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000775 if (!self->string)
776 return NULL;
777 }
778 Py_INCREF(self->string);
779 return self->string;
780}
781
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000782static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000783PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000784{
785 char *s;
786 int len;
787 if (self->string && PyUnicode_Check(self->string)) {
788 Py_INCREF(self->string);
789 return self->string;
790 }
791 /* XXX Could chache result if it is non-ASCII. */
792 s = Tcl_GetStringFromObj(self->value, &len);
793 return PyUnicode_DecodeUTF8(s, len, "strict");
794}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000795
Martin v. Löwisffad6332002-11-26 09:28:05 +0000796static PyObject *
797PyTclObject_repr(PyTclObject *self)
798{
Walter Dörwald7569dfe2007-05-19 21:49:49 +0000799 return PyUnicode_FromFormat("<%s object at %p>",
800 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000801}
802
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000803static int
804PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
805{
806 int res;
807 res = strcmp(Tcl_GetString(self->value),
808 Tcl_GetString(other->value));
809 if (res < 0) return -1;
810 if (res > 0) return 1;
811 return 0;
812}
813
Martin v. Löwis39195712003-01-04 00:33:13 +0000814PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
815
Martin v. Löwisffad6332002-11-26 09:28:05 +0000816static PyObject*
817get_typename(PyTclObject* obj, void* ignored)
818{
819 return PyString_FromString(obj->value->typePtr->name);
820}
821
Martin v. Löwis39195712003-01-04 00:33:13 +0000822
Martin v. Löwisffad6332002-11-26 09:28:05 +0000823static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000824 {"typename", (getter)get_typename, NULL, get_typename__doc__},
825 {"string", (getter)PyTclObject_string, NULL,
826 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000827 {0},
828};
829
Neal Norwitz227b5332006-03-22 09:28:35 +0000830static PyTypeObject PyTclObject_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000831 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000832 "_tkinter.Tcl_Obj", /*tp_name*/
833 sizeof(PyTclObject), /*tp_basicsize*/
834 0, /*tp_itemsize*/
835 /* methods */
836 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
837 0, /*tp_print*/
838 0, /*tp_getattr*/
839 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000840 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000841 (reprfunc)PyTclObject_repr, /*tp_repr*/
842 0, /*tp_as_number*/
843 0, /*tp_as_sequence*/
844 0, /*tp_as_mapping*/
845 0, /*tp_hash*/
846 0, /*tp_call*/
847 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000848 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000849 0, /*tp_setattro*/
850 0, /*tp_as_buffer*/
851 Py_TPFLAGS_DEFAULT, /*tp_flags*/
852 0, /*tp_doc*/
853 0, /*tp_traverse*/
854 0, /*tp_clear*/
855 0, /*tp_richcompare*/
856 0, /*tp_weaklistoffset*/
857 0, /*tp_iter*/
858 0, /*tp_iternext*/
Walter Dörwald6720d912007-07-12 12:12:25 +0000859 0, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000860 0, /*tp_members*/
861 PyTclObject_getsetlist, /*tp_getset*/
862 0, /*tp_base*/
863 0, /*tp_dict*/
864 0, /*tp_descr_get*/
865 0, /*tp_descr_set*/
866 0, /*tp_dictoffset*/
867 0, /*tp_init*/
868 0, /*tp_alloc*/
869 0, /*tp_new*/
870 0, /*tp_free*/
871 0, /*tp_is_gc*/
872};
873
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000874static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000875AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000876{
877 Tcl_Obj *result;
878
879 if (PyString_Check(value))
880 return Tcl_NewStringObj(PyString_AS_STRING(value),
881 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000882 else if (PyBool_Check(value))
883 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossumddefaf32007-01-14 03:31:43 +0000884 else if (PyInt_CheckExact(value))
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000885 return Tcl_NewLongObj(PyInt_AS_LONG(value));
886 else if (PyFloat_Check(value))
887 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
888 else if (PyTuple_Check(value)) {
889 Tcl_Obj **argv = (Tcl_Obj**)
890 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
891 int i;
892 if(!argv)
893 return 0;
894 for(i=0;i<PyTuple_Size(value);i++)
895 argv[i] = AsObj(PyTuple_GetItem(value,i));
896 result = Tcl_NewListObj(PyTuple_Size(value), argv);
897 ckfree(FREECAST argv);
898 return result;
899 }
900 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000901 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000902 Py_ssize_t size = PyUnicode_GET_SIZE(value);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000903 /* This #ifdef assumes that Tcl uses UCS-2.
904 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000905#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000906 Tcl_UniChar *outbuf;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000907 Py_ssize_t i;
908 assert(size < size * sizeof(Tcl_UniChar));
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000909 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
910 if (!outbuf) {
911 PyErr_NoMemory();
912 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000913 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000914 for (i = 0; i < size; i++) {
915 if (inbuf[i] >= 0x10000) {
916 /* Tcl doesn't do UTF-16, yet. */
917 PyErr_SetString(PyExc_ValueError,
918 "unsupported character");
919 ckfree(FREECAST outbuf);
920 return NULL;
921 }
922 outbuf[i] = inbuf[i];
923 }
924 result = Tcl_NewUnicodeObj(outbuf, size);
925 ckfree(FREECAST outbuf);
926 return result;
927#else
928 return Tcl_NewUnicodeObj(inbuf, size);
929#endif
930
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000931 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000932 else if(PyTclObject_Check(value)) {
933 Tcl_Obj *v = ((PyTclObject*)value)->value;
934 Tcl_IncrRefCount(v);
935 return v;
936 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000937 else {
938 PyObject *v = PyObject_Str(value);
939 if (!v)
940 return 0;
941 result = AsObj(v);
942 Py_DECREF(v);
943 return result;
944 }
945}
946
Martin v. Löwisffad6332002-11-26 09:28:05 +0000947static PyObject*
948FromObj(PyObject* tkapp, Tcl_Obj *value)
949{
950 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000951 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000952
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000953 if (value->typePtr == NULL) {
954 /* If the result contains any bytes with the top bit set,
955 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000956 int i;
957 char *s = value->bytes;
958 int len = value->length;
959 for (i = 0; i < len; i++) {
960 if (value->bytes[i] & 0x80)
961 break;
962 }
963
964 if (i == value->length)
965 result = PyString_FromStringAndSize(s, len);
966 else {
967 /* Convert UTF-8 to Unicode string */
968 result = PyUnicode_DecodeUTF8(s, len, "strict");
969 if (result == NULL) {
970 PyErr_Clear();
971 result = PyString_FromStringAndSize(s, len);
972 }
973 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000974 return result;
975 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000976
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000977 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000978 result = value->internalRep.longValue ? Py_True : Py_False;
979 Py_INCREF(result);
980 return result;
981 }
982
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000983 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000984 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000985 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000986 return PyString_FromStringAndSize(data, size);
987 }
988
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000989 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000990 return PyFloat_FromDouble(value->internalRep.doubleValue);
991 }
992
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000993 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000994 return PyInt_FromLong(value->internalRep.longValue);
995 }
996
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000997 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000998 int size;
999 int i, status;
1000 PyObject *elem;
1001 Tcl_Obj *tcl_elem;
1002
1003 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1004 if (status == TCL_ERROR)
1005 return Tkinter_Error(tkapp);
1006 result = PyTuple_New(size);
1007 if (!result)
1008 return NULL;
1009 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001010 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001011 value, i, &tcl_elem);
1012 if (status == TCL_ERROR) {
1013 Py_DECREF(result);
1014 return Tkinter_Error(tkapp);
1015 }
1016 elem = FromObj(tkapp, tcl_elem);
1017 if (!elem) {
1018 Py_DECREF(result);
1019 return NULL;
1020 }
1021 PyTuple_SetItem(result, i, elem);
1022 }
1023 return result;
1024 }
1025
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001026 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001027 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001028 }
1029
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001030 if (value->typePtr == app->StringType) {
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001031#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001032 PyObject *result;
1033 int size;
1034 Tcl_UniChar *input;
1035 Py_UNICODE *output;
1036
1037 size = Tcl_GetCharLength(value);
1038 result = PyUnicode_FromUnicode(NULL, size);
1039 if (!result)
1040 return NULL;
1041 input = Tcl_GetUnicode(value);
1042 output = PyUnicode_AS_UNICODE(result);
1043 while (size--)
1044 *output++ = *input++;
1045 return result;
1046#else
1047 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1048 Tcl_GetCharLength(value));
1049#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +00001050 }
1051
1052 return newPyTclObject(value);
1053}
1054
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001055/* This mutex synchronizes inter-thread command calls. */
1056
1057TCL_DECLARE_MUTEX(call_mutex)
1058
1059typedef struct Tkapp_CallEvent {
1060 Tcl_Event ev; /* Must be first */
1061 TkappObject *self;
1062 PyObject *args;
1063 int flags;
1064 PyObject **res;
1065 PyObject **exc_type, **exc_value, **exc_tb;
1066 Tcl_Condition done;
1067} Tkapp_CallEvent;
1068
1069void
1070Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001071{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001072 int i;
1073 for (i = 0; i < objc; i++)
1074 Tcl_DecrRefCount(objv[i]);
1075 if (objv != objStore)
1076 ckfree(FREECAST objv);
1077}
Guido van Rossum18468821994-06-20 07:49:28 +00001078
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001079/* Convert Python objects to Tcl objects. This must happen in the
1080 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001081
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001082static Tcl_Obj**
1083Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1084{
1085 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001086 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001087 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001088 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001089
Guido van Rossum212643f1998-04-29 16:22:14 +00001090 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001091 objv[0] = AsObj(args);
1092 if (objv[0] == 0)
1093 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001094 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001095 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001096 }
1097 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001098 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001099
Guido van Rossum632de272000-03-29 00:19:50 +00001100 if (objc > ARGSZ) {
1101 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1102 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001103 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001104 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001105 goto finally;
1106 }
1107 }
1108
Guido van Rossum632de272000-03-29 00:19:50 +00001109 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001110 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001111 if (v == Py_None) {
1112 objc = i;
1113 break;
1114 }
Guido van Rossum632de272000-03-29 00:19:50 +00001115 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001116 if (!objv[i]) {
1117 /* Reset objc, so it attempts to clear
1118 objects only up to i. */
1119 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001120 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001121 }
Guido van Rossum632de272000-03-29 00:19:50 +00001122 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001123 }
1124 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001125 *pobjc = objc;
1126 return objv;
1127finally:
1128 Tkapp_CallDeallocArgs(objv, objStore, objc);
1129 return NULL;
1130}
Guido van Rossum212643f1998-04-29 16:22:14 +00001131
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001132/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001133
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001134static PyObject*
1135Tkapp_CallResult(TkappObject *self)
1136{
1137 PyObject *res = NULL;
1138 if(self->wantobjects) {
1139 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001140 /* Not sure whether the IncrRef is necessary, but something
1141 may overwrite the interpreter result while we are
1142 converting it. */
1143 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001144 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001145 Tcl_DecrRefCount(value);
1146 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001147 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001148 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001149
Guido van Rossum990f5c62000-05-04 15:07:16 +00001150 /* If the result contains any bytes with the top bit set,
1151 it's UTF-8 and we should decode it to Unicode */
1152 while (*p != '\0') {
1153 if (*p & 0x80)
1154 break;
1155 p++;
1156 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001157
Guido van Rossum990f5c62000-05-04 15:07:16 +00001158 if (*p == '\0')
1159 res = PyString_FromStringAndSize(s, (int)(p-s));
1160 else {
1161 /* Convert UTF-8 to Unicode string */
1162 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001163 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1164 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001165 PyErr_Clear();
1166 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001167 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001168 }
1169 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001170 return res;
1171}
Guido van Rossum632de272000-03-29 00:19:50 +00001172
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001173/* Tkapp_CallProc is the event procedure that is executed in the context of
1174 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1175 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001176
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001177static int
1178Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1179{
1180 Tcl_Obj *objStore[ARGSZ];
1181 Tcl_Obj **objv;
1182 int objc;
1183 int i;
1184 ENTER_PYTHON
1185 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1186 if (!objv) {
1187 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1188 *(e->res) = NULL;
1189 }
1190 LEAVE_PYTHON
1191 if (!objv)
1192 goto done;
1193 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1194 ENTER_PYTHON
1195 if (i == TCL_ERROR) {
1196 *(e->res) = NULL;
1197 *(e->exc_type) = NULL;
1198 *(e->exc_tb) = NULL;
1199 *(e->exc_value) = PyObject_CallFunction(
1200 Tkinter_TclError, "s",
1201 Tcl_GetStringResult(e->self->interp));
1202 }
1203 else {
1204 *(e->res) = Tkapp_CallResult(e->self);
1205 }
1206 LEAVE_PYTHON
1207 done:
1208 /* Wake up calling thread. */
1209 Tcl_MutexLock(&call_mutex);
1210 Tcl_ConditionNotify(&e->done);
1211 Tcl_MutexUnlock(&call_mutex);
1212 return 1;
1213}
1214
1215/* This is the main entry point for calling a Tcl command.
1216 It supports three cases, with regard to threading:
1217 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1218 the context of the calling thread.
1219 2. Tcl is threaded, caller of the command is in the interpreter thread:
1220 Execute the command in the calling thread. Since the Tcl lock will
1221 not be used, we can merge that with case 1.
1222 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1223 the interpreter thread. Allocation of Tcl objects needs to occur in the
1224 interpreter thread, so we ship the PyObject* args to the target thread,
1225 and perform processing there. */
1226
1227static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001228Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001229{
1230 Tcl_Obj *objStore[ARGSZ];
1231 Tcl_Obj **objv = NULL;
1232 int objc, i;
1233 PyObject *res = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001234 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001235 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1236 int flags = TCL_EVAL_DIRECT;
1237
Guido van Rossum992d4a32007-07-11 13:09:30 +00001238 /* If args is a single tuple, replace with contents of tuple */
1239 if (1 == PyTuple_Size(args)){
1240 PyObject* item = PyTuple_GetItem(args, 0);
1241 if (PyTuple_Check(item))
1242 args = item;
1243 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001244#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001245 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1246 /* We cannot call the command directly. Instead, we must
1247 marshal the parameters to the interpreter thread. */
1248 Tkapp_CallEvent *ev;
1249 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001250 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001251 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001252 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1253 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1254 ev->self = self;
1255 ev->args = args;
1256 ev->res = &res;
1257 ev->exc_type = &exc_type;
1258 ev->exc_value = &exc_value;
1259 ev->exc_tb = &exc_tb;
1260 ev->done = (Tcl_Condition)0;
1261
1262 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1263
1264 if (res == NULL) {
1265 if (exc_type)
1266 PyErr_Restore(exc_type, exc_value, exc_tb);
1267 else
1268 PyErr_SetObject(Tkinter_TclError, exc_value);
1269 }
1270 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001271 else
1272#endif
1273 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001274
1275 objv = Tkapp_CallArgs(args, objStore, &objc);
1276 if (!objv)
1277 return NULL;
1278
1279 ENTER_TCL
1280
1281 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1282
1283 ENTER_OVERLAP
1284
1285 if (i == TCL_ERROR)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001286 Tkinter_Error(selfptr);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001287 else
1288 res = Tkapp_CallResult(self);
1289
1290 LEAVE_OVERLAP_TCL
1291
1292 Tkapp_CallDeallocArgs(objv, objStore, objc);
1293 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001294 return res;
1295}
1296
1297
1298static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001299Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001300{
Guido van Rossum212643f1998-04-29 16:22:14 +00001301 /* Could do the same here as for Tkapp_Call(), but this is not used
1302 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1303 way for the user to do what all its Global* variants do (save and
1304 reset the scope pointer, call the local version, restore the saved
1305 scope pointer). */
1306
Guido van Rossum62320c91998-06-15 04:36:09 +00001307 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001308 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001309
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001310 CHECK_TCL_APPARTMENT;
1311
Guido van Rossum62320c91998-06-15 04:36:09 +00001312 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001313 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001314 int err;
1315 ENTER_TCL
1316 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001317 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001318 if (err == TCL_ERROR)
1319 res = Tkinter_Error(self);
1320 else
1321 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001322 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001323 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001324 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001325
1326 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001327}
1328
1329static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001330Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001331{
Barry Warsawfa701a81997-01-16 00:15:11 +00001332 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001333 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001334 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001335
Guido van Rossum43713e52000-02-29 13:59:29 +00001336 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001337 return NULL;
1338
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001339 CHECK_TCL_APPARTMENT;
1340
Guido van Rossum00d93061998-05-28 23:06:38 +00001341 ENTER_TCL
1342 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001343 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001344 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001345 res = Tkinter_Error(self);
1346 else
1347 res = PyString_FromString(Tkapp_Result(self));
1348 LEAVE_OVERLAP_TCL
1349 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001350}
1351
1352static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001353Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001354{
Barry Warsawfa701a81997-01-16 00:15:11 +00001355 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001356 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001357 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001358
Guido van Rossum43713e52000-02-29 13:59:29 +00001359 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001360 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001361
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001362 CHECK_TCL_APPARTMENT;
1363
Guido van Rossum00d93061998-05-28 23:06:38 +00001364 ENTER_TCL
1365 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001366 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001367 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001368 res = Tkinter_Error(self);
1369 else
1370 res = PyString_FromString(Tkapp_Result(self));
1371 LEAVE_OVERLAP_TCL
1372 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001373}
1374
1375static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001376Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001377{
Barry Warsawfa701a81997-01-16 00:15:11 +00001378 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001379 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001380 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001381
Guido van Rossum43713e52000-02-29 13:59:29 +00001382 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001383 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001384
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001385 CHECK_TCL_APPARTMENT;
1386
Guido van Rossum00d93061998-05-28 23:06:38 +00001387 ENTER_TCL
1388 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001389 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001390 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001391 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001392
Guido van Rossum62320c91998-06-15 04:36:09 +00001393 else
1394 res = PyString_FromString(Tkapp_Result(self));
1395 LEAVE_OVERLAP_TCL
1396 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001397}
1398
1399static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001400Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001401{
Barry Warsawfa701a81997-01-16 00:15:11 +00001402 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001403 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001404 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001405
Guido van Rossum35d43371997-08-02 00:09:09 +00001406 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001407 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001408
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001409 CHECK_TCL_APPARTMENT;
1410
Guido van Rossum00d93061998-05-28 23:06:38 +00001411 ENTER_TCL
1412 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001413 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001414 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001415 res = Tkinter_Error(self);
1416 else
1417 res = PyString_FromString(Tkapp_Result(self));
1418 LEAVE_OVERLAP_TCL
1419 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001420}
1421
1422static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001423Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001424{
Barry Warsawfa701a81997-01-16 00:15:11 +00001425 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001426
Guido van Rossum43713e52000-02-29 13:59:29 +00001427 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001428 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001429 CHECK_TCL_APPARTMENT;
1430
Guido van Rossum00d93061998-05-28 23:06:38 +00001431 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001432 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001433 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001434
Barry Warsawfa701a81997-01-16 00:15:11 +00001435 Py_INCREF(Py_None);
1436 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001437}
1438
Barry Warsawfa701a81997-01-16 00:15:11 +00001439
1440
Guido van Rossum18468821994-06-20 07:49:28 +00001441/** Tcl Variable **/
1442
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001443TCL_DECLARE_MUTEX(var_mutex)
1444
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001445typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001446typedef struct VarEvent {
1447 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001448 PyObject *self;
1449 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001450 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001451 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001452 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001453 PyObject **exc_type;
1454 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001455 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001456} VarEvent;
1457
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001458static int
1459varname_converter(PyObject *in, void *_out)
1460{
1461 char **out = (char**)_out;
1462 if (PyString_Check(in)) {
1463 *out = PyString_AsString(in);
1464 return 1;
1465 }
1466 if (PyTclObject_Check(in)) {
1467 *out = PyTclObject_TclString(in);
1468 return 1;
1469 }
1470 /* XXX: Should give diagnostics. */
1471 return 0;
1472}
1473
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001474void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001475var_perform(VarEvent *ev)
1476{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001477 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1478 if (!*(ev->res)) {
1479 PyObject *exc, *val, *tb;
1480 PyErr_Fetch(&exc, &val, &tb);
1481 PyErr_NormalizeException(&exc, &val, &tb);
1482 *(ev->exc_type) = exc;
1483 *(ev->exc_val) = val;
1484 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001485 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001486
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001487}
1488
1489static int
1490var_proc(VarEvent* ev, int flags)
1491{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001492 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001493 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001494 Tcl_MutexLock(&var_mutex);
1495 Tcl_ConditionNotify(&ev->cond);
1496 Tcl_MutexUnlock(&var_mutex);
1497 LEAVE_PYTHON
1498 return 1;
1499}
1500
1501static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001502var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001503{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001504 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001505#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001506 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001507 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001508 VarEvent *ev;
1509 PyObject *res, *exc_type, *exc_val;
1510
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001511 /* The current thread is not the interpreter thread. Marshal
1512 the call to the interpreter thread, then wait for
1513 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001514 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001515 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001516
1517 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1518
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001519 ev->self = selfptr;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001520 ev->args = args;
1521 ev->flags = flags;
1522 ev->func = func;
1523 ev->res = &res;
1524 ev->exc_type = &exc_type;
1525 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001526 ev->cond = NULL;
1527 ev->ev.proc = (Tcl_EventProc*)var_proc;
1528 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001529 if (!res) {
1530 PyErr_SetObject(exc_type, exc_val);
1531 Py_DECREF(exc_type);
1532 Py_DECREF(exc_val);
1533 return NULL;
1534 }
1535 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001537#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001538 /* Tcl is not threaded, or this is the interpreter thread. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001539 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001540}
1541
Guido van Rossum18468821994-06-20 07:49:28 +00001542static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001543SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001544{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001545 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001546 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001547 PyObject *res = NULL;
1548 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001549
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001550 if (PyArg_ParseTuple(args, "O&O:setvar",
1551 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001552 /* XXX Acquire tcl lock??? */
1553 newval = AsObj(newValue);
1554 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001555 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001556 ENTER_TCL
1557 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1558 newval, flags);
1559 ENTER_OVERLAP
1560 if (!ok)
1561 Tkinter_Error(self);
1562 else {
1563 res = Py_None;
1564 Py_INCREF(res);
1565 }
1566 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001567 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001568 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001569 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001570 if (PyArg_ParseTuple(args, "ssO:setvar",
1571 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001572 /* XXX must hold tcl lock already??? */
1573 newval = AsObj(newValue);
1574 ENTER_TCL
1575 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1576 ENTER_OVERLAP
1577 if (!ok)
1578 Tkinter_Error(self);
1579 else {
1580 res = Py_None;
1581 Py_INCREF(res);
1582 }
1583 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001584 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001585 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001586 return NULL;
1587 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001588 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001589 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001590}
1591
1592static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001593Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001594{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001595 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001596}
1597
1598static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001599Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001600{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001601 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001602}
1603
Barry Warsawfa701a81997-01-16 00:15:11 +00001604
1605
Guido van Rossum18468821994-06-20 07:49:28 +00001606static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001607GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001608{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001609 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001610 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001611 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001612
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001613 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1614 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001615 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001616
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001617 ENTER_TCL
1618 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1619 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001620 if (tres == NULL) {
1621 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1622 } else {
1623 if (((TkappObject*)self)->wantobjects) {
1624 res = FromObj(self, tres);
1625 }
1626 else {
1627 res = PyString_FromString(Tcl_GetString(tres));
1628 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001629 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001630 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001631 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001632}
1633
1634static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001635Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001636{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001637 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001638}
1639
1640static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001641Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001642{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001643 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001644}
1645
Barry Warsawfa701a81997-01-16 00:15:11 +00001646
1647
Guido van Rossum18468821994-06-20 07:49:28 +00001648static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001649UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001650{
Guido van Rossum35d43371997-08-02 00:09:09 +00001651 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001652 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001653 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001654
Guido van Rossum43713e52000-02-29 13:59:29 +00001655 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001656 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001657
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001658 ENTER_TCL
1659 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1660 ENTER_OVERLAP
1661 if (code == TCL_ERROR)
1662 res = Tkinter_Error(self);
1663 else {
1664 Py_INCREF(Py_None);
1665 res = Py_None;
1666 }
1667 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001668 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001669}
1670
1671static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001672Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001673{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001674 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001675}
1676
1677static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001678Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001679{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001680 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001681}
1682
Barry Warsawfa701a81997-01-16 00:15:11 +00001683
1684
Guido van Rossum18468821994-06-20 07:49:28 +00001685/** Tcl to Python **/
1686
1687static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001688Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001689{
Barry Warsawfa701a81997-01-16 00:15:11 +00001690 char *s;
1691 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001692
Martin v. Löwisffad6332002-11-26 09:28:05 +00001693 if (PyTuple_Size(args) == 1) {
1694 PyObject* o = PyTuple_GetItem(args, 0);
1695 if (PyInt_Check(o)) {
1696 Py_INCREF(o);
1697 return o;
1698 }
1699 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001700 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001701 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001702 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001703 return Tkinter_Error(self);
1704 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001705}
1706
1707static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001708Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001709{
Barry Warsawfa701a81997-01-16 00:15:11 +00001710 char *s;
1711 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001712
Martin v. Löwisffad6332002-11-26 09:28:05 +00001713 if (PyTuple_Size(args) == 1) {
1714 PyObject *o = PyTuple_GetItem(args, 0);
1715 if (PyFloat_Check(o)) {
1716 Py_INCREF(o);
1717 return o;
1718 }
1719 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001720 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001721 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001722 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001723 return Tkinter_Error(self);
1724 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001725}
1726
1727static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001728Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001729{
Barry Warsawfa701a81997-01-16 00:15:11 +00001730 char *s;
1731 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001732
Martin v. Löwisffad6332002-11-26 09:28:05 +00001733 if (PyTuple_Size(args) == 1) {
1734 PyObject *o = PyTuple_GetItem(args, 0);
1735 if (PyInt_Check(o)) {
1736 Py_INCREF(o);
1737 return o;
1738 }
1739 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001740 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001741 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001742 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1743 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001744 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001745}
1746
1747static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001748Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001749{
Barry Warsawfa701a81997-01-16 00:15:11 +00001750 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001751 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001752 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001753
Guido van Rossum43713e52000-02-29 13:59:29 +00001754 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001755 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001756
1757 CHECK_TCL_APPARTMENT;
1758
Guido van Rossum00d93061998-05-28 23:06:38 +00001759 ENTER_TCL
1760 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001761 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001762 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001763 res = Tkinter_Error(self);
1764 else
1765 res = Py_BuildValue("s", Tkapp_Result(self));
1766 LEAVE_OVERLAP_TCL
1767 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001768}
1769
1770static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001771Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001772{
Barry Warsawfa701a81997-01-16 00:15:11 +00001773 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001774 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001775 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001776 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001777
Guido van Rossum43713e52000-02-29 13:59:29 +00001778 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001779 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001780
1781 CHECK_TCL_APPARTMENT;
1782
Guido van Rossum00d93061998-05-28 23:06:38 +00001783 ENTER_TCL
1784 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001785 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001786 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001787 res = Tkinter_Error(self);
1788 else
1789 res = Py_BuildValue("l", v);
1790 LEAVE_OVERLAP_TCL
1791 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001792}
1793
1794static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001795Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001796{
Barry Warsawfa701a81997-01-16 00:15:11 +00001797 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001798 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001799 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001800 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001801
Guido van Rossum43713e52000-02-29 13:59:29 +00001802 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001803 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001804 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001805 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001806 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001807 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001808 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001809 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001810 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001811 res = Tkinter_Error(self);
1812 else
1813 res = Py_BuildValue("d", v);
1814 LEAVE_OVERLAP_TCL
1815 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001816}
1817
1818static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001819Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001820{
Barry Warsawfa701a81997-01-16 00:15:11 +00001821 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001822 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001823 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001824 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001825
Guido van Rossum43713e52000-02-29 13:59:29 +00001826 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001827 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001828 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001829 ENTER_TCL
1830 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001831 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001832 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001833 res = Tkinter_Error(self);
1834 else
1835 res = Py_BuildValue("i", v);
1836 LEAVE_OVERLAP_TCL
1837 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001838}
1839
Barry Warsawfa701a81997-01-16 00:15:11 +00001840
1841
Guido van Rossum18468821994-06-20 07:49:28 +00001842static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001843Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001844{
Barry Warsawfa701a81997-01-16 00:15:11 +00001845 char *list;
1846 int argc;
1847 char **argv;
1848 PyObject *v;
1849 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001850
Martin v. Löwisffad6332002-11-26 09:28:05 +00001851 if (PyTuple_Size(args) == 1) {
1852 v = PyTuple_GetItem(args, 0);
1853 if (PyTuple_Check(v)) {
1854 Py_INCREF(v);
1855 return v;
1856 }
1857 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001858 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001859 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001860
Neal Norwitzd1c55102003-05-29 00:17:03 +00001861 if (Tcl_SplitList(Tkapp_Interp(self), list,
1862 &argc, &argv) == TCL_ERROR) {
1863 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001864 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001865 }
Guido van Rossum18468821994-06-20 07:49:28 +00001866
Barry Warsawfa701a81997-01-16 00:15:11 +00001867 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001868 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001869
Barry Warsawfa701a81997-01-16 00:15:11 +00001870 for (i = 0; i < argc; i++) {
1871 PyObject *s = PyString_FromString(argv[i]);
1872 if (!s || PyTuple_SetItem(v, i, s)) {
1873 Py_DECREF(v);
1874 v = NULL;
1875 goto finally;
1876 }
1877 }
Guido van Rossum18468821994-06-20 07:49:28 +00001878
Barry Warsawfa701a81997-01-16 00:15:11 +00001879 finally:
1880 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001881 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001882 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001883}
1884
1885static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001886Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001887{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001888 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001889 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001890
Martin v. Löwisffad6332002-11-26 09:28:05 +00001891 if (PyTuple_Size(args) == 1) {
1892 PyObject* o = PyTuple_GetItem(args, 0);
1893 if (PyTuple_Check(o)) {
1894 o = SplitObj(o);
1895 return o;
1896 }
1897 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001898 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001899 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001900 v = Split(list);
1901 PyMem_Free(list);
1902 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001903}
1904
1905static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001906Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001907{
Barry Warsawfa701a81997-01-16 00:15:11 +00001908 char *s = Merge(args);
1909 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001910
Barry Warsawfa701a81997-01-16 00:15:11 +00001911 if (s) {
1912 res = PyString_FromString(s);
1913 ckfree(s);
1914 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001915
1916 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001917}
1918
Barry Warsawfa701a81997-01-16 00:15:11 +00001919
1920
Guido van Rossum18468821994-06-20 07:49:28 +00001921/** Tcl Command **/
1922
Guido van Rossum00d93061998-05-28 23:06:38 +00001923/* Client data struct */
1924typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001925 PyObject *self;
1926 PyObject *func;
1927} PythonCmd_ClientData;
1928
1929static int
Fred Drake509d79a2000-07-08 04:04:38 +00001930PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001931{
1932 errorInCmd = 1;
1933 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1934 LEAVE_PYTHON
1935 return TCL_ERROR;
1936}
1937
Guido van Rossum18468821994-06-20 07:49:28 +00001938/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001939 * function or method.
1940 */
Guido van Rossum18468821994-06-20 07:49:28 +00001941static int
Fred Drake509d79a2000-07-08 04:04:38 +00001942PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001943{
Guido van Rossum00d93061998-05-28 23:06:38 +00001944 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001945 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001946 int i, rv;
1947 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001948
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001949 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001950
Barry Warsawfa701a81997-01-16 00:15:11 +00001951 /* TBD: no error checking here since we know, via the
1952 * Tkapp_CreateCommand() that the client data is a two-tuple
1953 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001954 self = data->self;
1955 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001956
Barry Warsawfa701a81997-01-16 00:15:11 +00001957 /* Create argument list (argv1, ..., argvN) */
1958 if (!(arg = PyTuple_New(argc - 1)))
1959 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001960
Barry Warsawfa701a81997-01-16 00:15:11 +00001961 for (i = 0; i < (argc - 1); i++) {
1962 PyObject *s = PyString_FromString(argv[i + 1]);
1963 if (!s || PyTuple_SetItem(arg, i, s)) {
1964 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001965 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001966 }
1967 }
1968 res = PyEval_CallObject(func, arg);
1969 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001970
Barry Warsawfa701a81997-01-16 00:15:11 +00001971 if (res == NULL)
1972 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001973
Barry Warsawfa701a81997-01-16 00:15:11 +00001974 if (!(tmp = PyList_New(0))) {
1975 Py_DECREF(res);
1976 return PythonCmd_Error(interp);
1977 }
1978
Guido van Rossum2834b972000-10-06 16:58:26 +00001979 s = AsString(res, tmp);
1980 if (s == NULL) {
1981 rv = PythonCmd_Error(interp);
1982 }
1983 else {
1984 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1985 rv = TCL_OK;
1986 }
1987
Barry Warsawfa701a81997-01-16 00:15:11 +00001988 Py_DECREF(res);
1989 Py_DECREF(tmp);
1990
Guido van Rossum00d93061998-05-28 23:06:38 +00001991 LEAVE_PYTHON
1992
Guido van Rossum2834b972000-10-06 16:58:26 +00001993 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001994}
1995
1996static void
Fred Drake509d79a2000-07-08 04:04:38 +00001997PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001998{
Guido van Rossum00d93061998-05-28 23:06:38 +00001999 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2000
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002001 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002002 Py_XDECREF(data->self);
2003 Py_XDECREF(data->func);
2004 PyMem_DEL(data);
2005 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002006}
2007
Barry Warsawfa701a81997-01-16 00:15:11 +00002008
2009
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002010
2011TCL_DECLARE_MUTEX(command_mutex)
2012
2013typedef struct CommandEvent{
2014 Tcl_Event ev;
2015 Tcl_Interp* interp;
2016 char *name;
2017 int create;
2018 int *status;
2019 ClientData *data;
2020 Tcl_Condition done;
2021} CommandEvent;
2022
2023static int
2024Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002025{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002026 if (ev->create)
2027 *ev->status = Tcl_CreateCommand(
2028 ev->interp, ev->name, PythonCmd,
2029 ev->data, PythonCmdDelete) == NULL;
2030 else
2031 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2032 Tcl_MutexLock(&command_mutex);
2033 Tcl_ConditionNotify(&ev->done);
2034 Tcl_MutexUnlock(&command_mutex);
2035 return 1;
2036}
2037
2038static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002039Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002040{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002041 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002042 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002043 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002044 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002045 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002046
Guido van Rossum43713e52000-02-29 13:59:29 +00002047 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002048 return NULL;
2049 if (!PyCallable_Check(func)) {
2050 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002051 return NULL;
2052 }
Guido van Rossum18468821994-06-20 07:49:28 +00002053
Martin v. Löwisa9656492003-03-30 08:44:58 +00002054#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002055 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002056 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002057 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002058#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002059
Guido van Rossum00d93061998-05-28 23:06:38 +00002060 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002061 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002062 return PyErr_NoMemory();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002063 Py_INCREF(self);
2064 Py_INCREF(func);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002065 data->self = selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002066 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002067
2068 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2069 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2070 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2071 ev->interp = self->interp;
2072 ev->create = 1;
2073 ev->name = cmdName;
2074 ev->data = (ClientData)data;
2075 ev->status = &err;
2076 ev->done = NULL;
2077 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2078 }
2079 else {
2080 ENTER_TCL
2081 err = Tcl_CreateCommand(
2082 Tkapp_Interp(self), cmdName, PythonCmd,
2083 (ClientData)data, PythonCmdDelete) == NULL;
2084 LEAVE_TCL
2085 }
2086 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002087 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002088 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002089 return NULL;
2090 }
Guido van Rossum18468821994-06-20 07:49:28 +00002091
Barry Warsawfa701a81997-01-16 00:15:11 +00002092 Py_INCREF(Py_None);
2093 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002094}
2095
Barry Warsawfa701a81997-01-16 00:15:11 +00002096
2097
Guido van Rossum18468821994-06-20 07:49:28 +00002098static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002099Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002100{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002101 TkappObject *self = (TkappObject*)selfptr;
Barry Warsawfa701a81997-01-16 00:15:11 +00002102 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002103 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002104
Guido van Rossum43713e52000-02-29 13:59:29 +00002105 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002106 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002107 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2108 CommandEvent *ev;
2109 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2110 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2111 ev->interp = self->interp;
2112 ev->create = 0;
2113 ev->name = cmdName;
2114 ev->status = &err;
2115 ev->done = NULL;
2116 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2117 &command_mutex);
2118 }
2119 else {
2120 ENTER_TCL
2121 err = Tcl_DeleteCommand(self->interp, cmdName);
2122 LEAVE_TCL
2123 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002124 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002125 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2126 return NULL;
2127 }
2128 Py_INCREF(Py_None);
2129 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002130}
2131
Barry Warsawfa701a81997-01-16 00:15:11 +00002132
2133
Guido van Rossum00d93061998-05-28 23:06:38 +00002134#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002135/** File Handler **/
2136
Guido van Rossum00d93061998-05-28 23:06:38 +00002137typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002138 PyObject *func;
2139 PyObject *file;
2140 int id;
2141 struct _fhcdata *next;
2142} FileHandler_ClientData;
2143
2144static FileHandler_ClientData *HeadFHCD;
2145
2146static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002147NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002148{
2149 FileHandler_ClientData *p;
2150 p = PyMem_NEW(FileHandler_ClientData, 1);
2151 if (p != NULL) {
2152 Py_XINCREF(func);
2153 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002154 p->func = func;
2155 p->file = file;
2156 p->id = id;
2157 p->next = HeadFHCD;
2158 HeadFHCD = p;
2159 }
2160 return p;
2161}
2162
2163static void
Fred Drake509d79a2000-07-08 04:04:38 +00002164DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002165{
2166 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002167
2168 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002169 while ((p = *pp) != NULL) {
2170 if (p->id == id) {
2171 *pp = p->next;
2172 Py_XDECREF(p->func);
2173 Py_XDECREF(p->file);
2174 PyMem_DEL(p);
2175 }
2176 else
2177 pp = &p->next;
2178 }
2179}
2180
Guido van Rossuma597dde1995-01-10 20:56:29 +00002181static void
Fred Drake509d79a2000-07-08 04:04:38 +00002182FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002183{
Guido van Rossum00d93061998-05-28 23:06:38 +00002184 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002185 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002186
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002187 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002188 func = data->func;
2189 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002190
Barry Warsawfa701a81997-01-16 00:15:11 +00002191 arg = Py_BuildValue("(Oi)", file, (long) mask);
2192 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002193 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002194
2195 if (res == NULL) {
2196 errorInCmd = 1;
2197 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2198 }
2199 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002200 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002201}
2202
Guido van Rossum18468821994-06-20 07:49:28 +00002203static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002204Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2205 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002206{
Guido van Rossum00d93061998-05-28 23:06:38 +00002207 FileHandler_ClientData *data;
2208 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002209 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002210
Guido van Rossum2834b972000-10-06 16:58:26 +00002211 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2212 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002213 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002214
Martin v. Löwisa9656492003-03-30 08:44:58 +00002215#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002216 if (!self && !tcl_lock) {
2217 /* We don't have the Tcl lock since Tcl is threaded. */
2218 PyErr_SetString(PyExc_RuntimeError,
2219 "_tkinter.createfilehandler not supported "
2220 "for threaded Tcl");
2221 return NULL;
2222 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002223#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002224
2225 if (self) {
2226 CHECK_TCL_APPARTMENT;
2227 }
2228
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002229 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002230 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002231 return NULL;
2232 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002233 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002234 return NULL;
2235 }
2236
Guido van Rossuma80649b2000-03-28 20:07:05 +00002237 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002238 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002239 return NULL;
2240
Barry Warsawfa701a81997-01-16 00:15:11 +00002241 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002242 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002243 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002244 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002245 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002246 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002247}
2248
2249static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002250Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002251{
Barry Warsawfa701a81997-01-16 00:15:11 +00002252 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002253 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002254
Guido van Rossum43713e52000-02-29 13:59:29 +00002255 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002256 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002257
Martin v. Löwisa9656492003-03-30 08:44:58 +00002258#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002259 if (!self && !tcl_lock) {
2260 /* We don't have the Tcl lock since Tcl is threaded. */
2261 PyErr_SetString(PyExc_RuntimeError,
2262 "_tkinter.deletefilehandler not supported "
2263 "for threaded Tcl");
2264 return NULL;
2265 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002266#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002267
2268 if (self) {
2269 CHECK_TCL_APPARTMENT;
2270 }
2271
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002272 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002273 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002274 return NULL;
2275
Guido van Rossuma80649b2000-03-28 20:07:05 +00002276 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002277
Barry Warsawfa701a81997-01-16 00:15:11 +00002278 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002279 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002280 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002281 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002282 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002283 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002284}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002285#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002286
Barry Warsawfa701a81997-01-16 00:15:11 +00002287
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002288/**** Tktt Object (timer token) ****/
2289
Jeremy Hylton938ace62002-07-17 16:30:39 +00002290static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002291
Guido van Rossum00d93061998-05-28 23:06:38 +00002292typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002293 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002294 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002295 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002296} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002297
2298static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002299Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002300{
Barry Warsawfa701a81997-01-16 00:15:11 +00002301 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002302 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002303
Guido van Rossum43713e52000-02-29 13:59:29 +00002304 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002305 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002306 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002307 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002308 v->token = NULL;
2309 }
2310 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002311 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002312 Py_DECREF(func);
2313 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002314 }
2315 Py_INCREF(Py_None);
2316 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002317}
2318
2319static PyMethodDef Tktt_methods[] =
2320{
Neal Norwitzb0493252002-03-31 14:44:22 +00002321 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002322 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002323};
2324
2325static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002326Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002327{
Barry Warsawfa701a81997-01-16 00:15:11 +00002328 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002329
Guido van Rossumb18618d2000-05-03 23:44:39 +00002330 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002331 if (v == NULL)
2332 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002333
Guido van Rossum00d93061998-05-28 23:06:38 +00002334 Py_INCREF(func);
2335 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002336 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002337
2338 /* Extra reference, deleted when called or when handler is deleted */
2339 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002340 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002341}
2342
2343static void
Fred Drake509d79a2000-07-08 04:04:38 +00002344Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002345{
Guido van Rossum00d93061998-05-28 23:06:38 +00002346 TkttObject *v = (TkttObject *)self;
2347 PyObject *func = v->func;
2348
2349 Py_XDECREF(func);
2350
Guido van Rossumb18618d2000-05-03 23:44:39 +00002351 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002352}
2353
Guido van Rossum597ac201998-05-12 14:36:19 +00002354static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002355Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002356{
Barry Warsawfa701a81997-01-16 00:15:11 +00002357 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002358 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002359
Tim Peters885d4572001-11-28 20:27:42 +00002360 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002361 v->func == NULL ? ", handler deleted" : "");
Walter Dörwald1ab83302007-05-18 17:15:44 +00002362 return PyUnicode_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002363}
2364
2365static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002366Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002367{
Barry Warsawfa701a81997-01-16 00:15:11 +00002368 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002369}
2370
2371static PyTypeObject Tktt_Type =
2372{
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00002373 PyVarObject_HEAD_INIT(NULL, 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002374 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002375 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002376 0, /*tp_itemsize */
2377 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002378 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002379 Tktt_GetAttr, /*tp_getattr */
2380 0, /*tp_setattr */
2381 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002382 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002383 0, /*tp_as_number */
2384 0, /*tp_as_sequence */
2385 0, /*tp_as_mapping */
2386 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002387};
2388
Barry Warsawfa701a81997-01-16 00:15:11 +00002389
2390
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002391/** Timer Handler **/
2392
2393static void
Fred Drake509d79a2000-07-08 04:04:38 +00002394TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002395{
Guido van Rossum00d93061998-05-28 23:06:38 +00002396 TkttObject *v = (TkttObject *)clientData;
2397 PyObject *func = v->func;
2398 PyObject *res;
2399
2400 if (func == NULL)
2401 return;
2402
2403 v->func = NULL;
2404
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002405 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002406
2407 res = PyEval_CallObject(func, NULL);
2408 Py_DECREF(func);
2409 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002410
Barry Warsawfa701a81997-01-16 00:15:11 +00002411 if (res == NULL) {
2412 errorInCmd = 1;
2413 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2414 }
2415 else
2416 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002417
2418 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002419}
2420
2421static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002422Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002423{
Barry Warsawfa701a81997-01-16 00:15:11 +00002424 int milliseconds;
2425 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002426 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002427
Guido van Rossum2834b972000-10-06 16:58:26 +00002428 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2429 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002430 return NULL;
2431 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002432 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002433 return NULL;
2434 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002435
Martin v. Löwisa9656492003-03-30 08:44:58 +00002436#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002437 if (!self && !tcl_lock) {
2438 /* We don't have the Tcl lock since Tcl is threaded. */
2439 PyErr_SetString(PyExc_RuntimeError,
2440 "_tkinter.createtimerhandler not supported "
2441 "for threaded Tcl");
2442 return NULL;
2443 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002444#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002445
2446 if (self) {
2447 CHECK_TCL_APPARTMENT;
2448 }
2449
Guido van Rossum00d93061998-05-28 23:06:38 +00002450 v = Tktt_New(func);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002451 if (v) {
2452 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2453 (ClientData)v);
2454 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002455
Guido van Rossum00d93061998-05-28 23:06:38 +00002456 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002457}
2458
Barry Warsawfa701a81997-01-16 00:15:11 +00002459
Guido van Rossum18468821994-06-20 07:49:28 +00002460/** Event Loop **/
2461
Guido van Rossum18468821994-06-20 07:49:28 +00002462static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002463Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002464{
Barry Warsawfa701a81997-01-16 00:15:11 +00002465 int threshold = 0;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002466 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002467#ifdef WITH_THREAD
2468 PyThreadState *tstate = PyThreadState_Get();
2469#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002470
Guido van Rossum43713e52000-02-29 13:59:29 +00002471 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002472 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002473
Martin v. Löwisa9656492003-03-30 08:44:58 +00002474#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002475 if (!self && !tcl_lock) {
2476 /* We don't have the Tcl lock since Tcl is threaded. */
2477 PyErr_SetString(PyExc_RuntimeError,
2478 "_tkinter.mainloop not supported "
2479 "for threaded Tcl");
2480 return NULL;
2481 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002482#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002483
2484 if (self) {
2485 CHECK_TCL_APPARTMENT;
2486 self->dispatching = 1;
2487 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002488
Barry Warsawfa701a81997-01-16 00:15:11 +00002489 quitMainLoop = 0;
2490 while (Tk_GetNumMainWindows() > threshold &&
2491 !quitMainLoop &&
2492 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002493 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002494 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002495
2496#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002497 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002498 /* Allow other Python threads to run. */
2499 ENTER_TCL
2500 result = Tcl_DoOneEvent(0);
2501 LEAVE_TCL
2502 }
2503 else {
2504 Py_BEGIN_ALLOW_THREADS
2505 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2506 tcl_tstate = tstate;
2507 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2508 tcl_tstate = NULL;
2509 if(tcl_lock)PyThread_release_lock(tcl_lock);
2510 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002511 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002512 Py_END_ALLOW_THREADS
2513 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002514#else
2515 result = Tcl_DoOneEvent(0);
2516#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002517
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002518 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002519 if (self)
2520 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002521 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002522 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002523 if (result < 0)
2524 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002525 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002526 if (self)
2527 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002528 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002529
Barry Warsawfa701a81997-01-16 00:15:11 +00002530 if (errorInCmd) {
2531 errorInCmd = 0;
2532 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2533 excInCmd = valInCmd = trbInCmd = NULL;
2534 return NULL;
2535 }
2536 Py_INCREF(Py_None);
2537 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002538}
2539
2540static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002541Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002542{
Guido van Rossum35d43371997-08-02 00:09:09 +00002543 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002544 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002545
Guido van Rossum43713e52000-02-29 13:59:29 +00002546 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002547 return NULL;
2548
Guido van Rossum00d93061998-05-28 23:06:38 +00002549 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002550 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002551 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002552 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002553}
2554
2555static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002556Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002557{
2558
Guido van Rossum43713e52000-02-29 13:59:29 +00002559 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002560 return NULL;
2561
2562 quitMainLoop = 1;
2563 Py_INCREF(Py_None);
2564 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002565}
2566
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002567static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002568Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002569{
2570
Guido van Rossum43713e52000-02-29 13:59:29 +00002571 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002572 return NULL;
2573
2574 return PyInt_FromLong((long)Tkapp_Interp(self));
2575}
2576
David Aschere2b4b322004-02-18 05:59:53 +00002577static PyObject *
2578Tkapp_TkInit(PyObject *self, PyObject *args)
2579{
Thomas Wouters477c8d52006-05-27 19:21:47 +00002580 static int has_failed;
David Aschere2b4b322004-02-18 05:59:53 +00002581 Tcl_Interp *interp = Tkapp_Interp(self);
Neal Norwitz44dbae82004-02-19 02:44:22 +00002582 Tk_Window main_window;
David Aschere2b4b322004-02-18 05:59:53 +00002583 const char * _tk_exists = NULL;
David Aschere2b4b322004-02-18 05:59:53 +00002584 int err;
Neal Norwitz44dbae82004-02-19 02:44:22 +00002585 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002586
Thomas Wouters477c8d52006-05-27 19:21:47 +00002587 /* In all current versions of Tk (including 8.4.13), Tk_Init
2588 deadlocks on the second call when the first call failed.
2589 To avoid the deadlock, we just refuse the second call through
2590 a static variable. */
2591 if (has_failed) {
2592 PyErr_SetString(Tkinter_TclError,
2593 "Calling Tk_Init again after a previous call failed might deadlock");
2594 return NULL;
2595 }
2596
David Aschere2b4b322004-02-18 05:59:53 +00002597 /* We want to guard against calling Tk_Init() multiple times */
2598 CHECK_TCL_APPARTMENT;
2599 ENTER_TCL
2600 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2601 ENTER_OVERLAP
2602 if (err == TCL_ERROR) {
Thomas Wouters477c8d52006-05-27 19:21:47 +00002603 /* This sets an exception, but we cannot return right
2604 away because we need to exit the overlap first. */
2605 Tkinter_Error(self);
David Aschere2b4b322004-02-18 05:59:53 +00002606 } else {
2607 _tk_exists = Tkapp_Result(self);
2608 }
2609 LEAVE_OVERLAP_TCL
2610 if (err == TCL_ERROR) {
2611 return NULL;
2612 }
2613 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2614 if (Tk_Init(interp) == TCL_ERROR) {
2615 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Thomas Wouters477c8d52006-05-27 19:21:47 +00002616 has_failed = 1;
David Aschere2b4b322004-02-18 05:59:53 +00002617 return NULL;
2618 }
2619 }
2620 Py_INCREF(Py_None);
2621 return Py_None;
2622}
Barry Warsawfa701a81997-01-16 00:15:11 +00002623
Martin v. Löwisffad6332002-11-26 09:28:05 +00002624static PyObject *
2625Tkapp_WantObjects(PyObject *self, PyObject *args)
2626{
2627
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002628 int wantobjects = -1;
2629 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002630 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002631 if (wantobjects == -1)
2632 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002633 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002634
2635 Py_INCREF(Py_None);
2636 return Py_None;
2637}
2638
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002639static PyObject *
2640Tkapp_WillDispatch(PyObject *self, PyObject *args)
2641{
2642
2643 ((TkappObject*)self)->dispatching = 1;
2644
2645 Py_INCREF(Py_None);
2646 return Py_None;
2647}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002648
Barry Warsawfa701a81997-01-16 00:15:11 +00002649
Guido van Rossum18468821994-06-20 07:49:28 +00002650/**** Tkapp Method List ****/
2651
2652static PyMethodDef Tkapp_methods[] =
2653{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002654 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002655 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Guido van Rossumd59da4b2007-05-22 18:11:13 +00002656 {"call", Tkapp_Call, METH_VARARGS},
2657 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002658 {"eval", Tkapp_Eval, METH_VARARGS},
2659 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2660 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2661 {"record", Tkapp_Record, METH_VARARGS},
2662 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2663 {"setvar", Tkapp_SetVar, METH_VARARGS},
2664 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2665 {"getvar", Tkapp_GetVar, METH_VARARGS},
2666 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2667 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2668 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2669 {"getint", Tkapp_GetInt, METH_VARARGS},
2670 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2671 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2672 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2673 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2674 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2675 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2676 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2677 {"split", Tkapp_Split, METH_VARARGS},
Guido van Rossumd59da4b2007-05-22 18:11:13 +00002678 {"merge", Tkapp_Merge, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002679 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2680 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002681#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002682 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2683 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002684#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002685 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2686 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2687 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2688 {"quit", Tkapp_Quit, METH_VARARGS},
2689 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Neal Norwitz44dbae82004-02-19 02:44:22 +00002690 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002691 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002692};
2693
Barry Warsawfa701a81997-01-16 00:15:11 +00002694
2695
Guido van Rossum18468821994-06-20 07:49:28 +00002696/**** Tkapp Type Methods ****/
2697
2698static void
Fred Drake509d79a2000-07-08 04:04:38 +00002699Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002700{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002701 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002702 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002703 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002704 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002705 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002706 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002707}
2708
2709static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002710Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002711{
Guido van Rossum35d43371997-08-02 00:09:09 +00002712 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002713}
2714
2715static PyTypeObject Tkapp_Type =
2716{
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00002717 PyVarObject_HEAD_INIT(NULL, 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002718 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002719 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002720 0, /*tp_itemsize */
2721 Tkapp_Dealloc, /*tp_dealloc */
2722 0, /*tp_print */
2723 Tkapp_GetAttr, /*tp_getattr */
2724 0, /*tp_setattr */
2725 0, /*tp_compare */
2726 0, /*tp_repr */
2727 0, /*tp_as_number */
2728 0, /*tp_as_sequence */
2729 0, /*tp_as_mapping */
2730 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002731};
2732
Barry Warsawfa701a81997-01-16 00:15:11 +00002733
2734
Guido van Rossum18468821994-06-20 07:49:28 +00002735/**** Tkinter Module ****/
2736
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002737typedef struct {
2738 PyObject* tuple;
2739 int size; /* current size */
2740 int maxsize; /* allocated size */
2741} FlattenContext;
2742
2743static int
2744_bump(FlattenContext* context, int size)
2745{
Guido van Rossum2834b972000-10-06 16:58:26 +00002746 /* expand tuple to hold (at least) size new items.
2747 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002748
2749 int maxsize = context->maxsize * 2;
2750
2751 if (maxsize < context->size + size)
2752 maxsize = context->size + size;
2753
2754 context->maxsize = maxsize;
2755
Tim Peters4324aa32001-05-28 22:30:08 +00002756 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002757}
2758
2759static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002760_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002761{
2762 /* add tuple or list to argument tuple (recursively) */
2763
2764 int i, size;
2765
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002766 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002767 PyErr_SetString(PyExc_ValueError,
2768 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002769 return 0;
2770 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002771 size = PyList_GET_SIZE(item);
2772 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002773 if (context->size + size > context->maxsize &&
2774 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002775 return 0;
2776 /* copy items to output tuple */
2777 for (i = 0; i < size; i++) {
2778 PyObject *o = PyList_GET_ITEM(item, i);
2779 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002780 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002781 return 0;
2782 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002783 if (context->size + 1 > context->maxsize &&
2784 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002785 return 0;
2786 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002787 PyTuple_SET_ITEM(context->tuple,
2788 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002789 }
2790 }
2791 } else if (PyTuple_Check(item)) {
2792 /* same, for tuples */
2793 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002794 if (context->size + size > context->maxsize &&
2795 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002796 return 0;
2797 for (i = 0; i < size; i++) {
2798 PyObject *o = PyTuple_GET_ITEM(item, i);
2799 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002800 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002801 return 0;
2802 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002803 if (context->size + 1 > context->maxsize &&
2804 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002805 return 0;
2806 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002807 PyTuple_SET_ITEM(context->tuple,
2808 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002809 }
2810 }
2811 } else {
2812 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2813 return 0;
2814 }
2815 return 1;
2816}
2817
2818static PyObject *
2819Tkinter_Flatten(PyObject* self, PyObject* args)
2820{
2821 FlattenContext context;
2822 PyObject* item;
2823
2824 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2825 return NULL;
2826
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002827 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002828 if (context.maxsize <= 0)
2829 return PyTuple_New(0);
2830
2831 context.tuple = PyTuple_New(context.maxsize);
2832 if (!context.tuple)
2833 return NULL;
2834
2835 context.size = 0;
2836
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002837 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002838 return NULL;
2839
Tim Peters4324aa32001-05-28 22:30:08 +00002840 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002841 return NULL;
2842
2843 return context.tuple;
2844}
2845
Guido van Rossum18468821994-06-20 07:49:28 +00002846static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002847Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002848{
Barry Warsawfa701a81997-01-16 00:15:11 +00002849 char *screenName = NULL;
2850 char *baseName = NULL;
2851 char *className = NULL;
2852 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002853 int wantobjects = 0;
David Aschere2b4b322004-02-18 05:59:53 +00002854 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002855 int sync = 0; /* pass -sync to wish */
2856 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002857
Guido van Rossum35d43371997-08-02 00:09:09 +00002858 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002859 if (baseName != NULL)
2860 baseName++;
2861 else
2862 baseName = Py_GetProgramName();
2863 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002864
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002865 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002866 &screenName, &baseName, &className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002867 &interactive, &wantobjects, &wantTk,
2868 &sync, &use))
Barry Warsawfa701a81997-01-16 00:15:11 +00002869 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002870
Barry Warsawfa701a81997-01-16 00:15:11 +00002871 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002872 interactive, wantobjects, wantTk,
2873 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002874}
2875
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002876static PyObject *
2877Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2878{
2879 int new_val;
2880 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2881 return NULL;
2882 if (new_val < 0) {
2883 PyErr_SetString(PyExc_ValueError,
2884 "busywaitinterval must be >= 0");
2885 return NULL;
2886 }
2887 Tkinter_busywaitinterval = new_val;
2888 Py_INCREF(Py_None);
2889 return Py_None;
2890}
2891
2892static char setbusywaitinterval_doc[] =
2893"setbusywaitinterval(n) -> None\n\
2894\n\
2895Set the busy-wait interval in milliseconds between successive\n\
2896calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2897It should be set to a divisor of the maximum time between\n\
2898frames in an animation.";
2899
2900static PyObject *
2901Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2902{
2903 return PyInt_FromLong(Tkinter_busywaitinterval);
2904}
2905
2906static char getbusywaitinterval_doc[] =
2907"getbusywaitinterval() -> int\n\
2908\n\
2909Return the current busy-wait interval between successive\n\
2910calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2911
Guido van Rossum18468821994-06-20 07:49:28 +00002912static PyMethodDef moduleMethods[] =
2913{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002914 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2915 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002916#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002917 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2918 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002919#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002920 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2921 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2922 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2923 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002924 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2925 setbusywaitinterval_doc},
2926 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2927 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002928 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002929};
2930
Guido van Rossum7bf15641998-05-22 18:28:17 +00002931#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002932
2933static int stdin_ready = 0;
2934
Guido van Rossumad4db171998-06-13 13:56:28 +00002935#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002936static void
Fred Drake509d79a2000-07-08 04:04:38 +00002937MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002938{
2939 stdin_ready = 1;
2940}
Guido van Rossumad4db171998-06-13 13:56:28 +00002941#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002942
Martin v. Löwisa9656492003-03-30 08:44:58 +00002943#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002944static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002945#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002946
Guido van Rossum18468821994-06-20 07:49:28 +00002947static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002948EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002949{
Guido van Rossumad4db171998-06-13 13:56:28 +00002950#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002951 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002952#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002953#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002954 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002955#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002956 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002957 errorInCmd = 0;
2958#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002959 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002960 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002961#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002962 while (!errorInCmd && !stdin_ready) {
2963 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002964#ifdef MS_WINDOWS
2965 if (_kbhit()) {
2966 stdin_ready = 1;
2967 break;
2968 }
2969#endif
2970#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002971 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002972 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002973 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002974
Guido van Rossum00d93061998-05-28 23:06:38 +00002975 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002976
2977 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002978 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002979 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002980 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002981 Py_END_ALLOW_THREADS
2982#else
2983 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002984#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002985
2986 if (result < 0)
2987 break;
2988 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002989#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002990 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002991#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002992 if (errorInCmd) {
2993 errorInCmd = 0;
2994 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2995 excInCmd = valInCmd = trbInCmd = NULL;
2996 PyErr_Print();
2997 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002998#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002999 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003000#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003001 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003002}
Guido van Rossum18468821994-06-20 07:49:28 +00003003
Guido van Rossum00d93061998-05-28 23:06:38 +00003004#endif
3005
Guido van Rossum7bf15641998-05-22 18:28:17 +00003006static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003007EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003008{
Guido van Rossum00d93061998-05-28 23:06:38 +00003009#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003010 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003011#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003012 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003013#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003014 PyOS_InputHook = EventHook;
3015 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003016#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003017}
3018
3019static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003020DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003021{
Guido van Rossum00d93061998-05-28 23:06:38 +00003022#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003023 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3024 PyOS_InputHook = NULL;
3025 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003026#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003027}
3028
Barry Warsawfa701a81997-01-16 00:15:11 +00003029
3030/* all errors will be checked in one fell swoop in init_tkinter() */
3031static void
Fred Drake509d79a2000-07-08 04:04:38 +00003032ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003033{
3034 PyObject *v = PyInt_FromLong(val);
3035 if (v) {
3036 PyDict_SetItemString(d, name, v);
3037 Py_DECREF(v);
3038 }
3039}
3040static void
Fred Drake509d79a2000-07-08 04:04:38 +00003041ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003042{
3043 PyObject *v = PyString_FromString(val);
3044 if (v) {
3045 PyDict_SetItemString(d, name, v);
3046 Py_DECREF(v);
3047 }
3048}
3049
3050
Mark Hammond62b1ab12002-07-23 06:31:15 +00003051PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003052init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003053{
Barry Warsawfa701a81997-01-16 00:15:11 +00003054 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003055
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00003056 Py_Type(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003057
3058#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003059 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003060#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003061
Barry Warsawfa701a81997-01-16 00:15:11 +00003062 m = Py_InitModule("_tkinter", moduleMethods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00003063 if (m == NULL)
3064 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003065
Barry Warsawfa701a81997-01-16 00:15:11 +00003066 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003067 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003068 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003069
Guido van Rossum35d43371997-08-02 00:09:09 +00003070 ins_long(d, "READABLE", TCL_READABLE);
3071 ins_long(d, "WRITABLE", TCL_WRITABLE);
3072 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3073 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3074 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3075 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3076 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3077 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3078 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003079 ins_string(d, "TK_VERSION", TK_VERSION);
3080 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003081
Guido van Rossum83551bf1997-09-13 00:44:23 +00003082 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003083
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00003084 Py_Type(&Tktt_Type) = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003085 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3086
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00003087 Py_Type(&PyTclObject_Type) = &PyType_Type;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003088 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003089
3090#ifdef TK_AQUA
3091 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3092 * start waking up. Note that Tcl_FindExecutable will do this, this
3093 * code must be above it! The original warning from
3094 * tkMacOSXAppInit.c is copied below.
3095 *
3096 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3097 * Tcl interpreter for now. It probably should work to do this
3098 * in the other order, but for now it doesn't seem to.
3099 *
3100 */
3101 Tk_MacOSXSetupTkNotifier();
3102#endif
3103
3104
Guido van Rossume187b0e2000-03-27 21:46:29 +00003105 /* This helps the dynamic loader; in Unicode aware Tcl versions
3106 it also helps Tcl find its encodings. */
3107 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003108
Barry Warsawfa701a81997-01-16 00:15:11 +00003109 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003110 return;
3111
Guido van Rossum43ff8681998-07-14 18:02:13 +00003112#if 0
3113 /* This was not a good idea; through <Destroy> bindings,
3114 Tcl_Finalize() may invoke Python code but at that point the
3115 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003116 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003117#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003118
Guido van Rossum18468821994-06-20 07:49:28 +00003119}