blob: 790a1be1646c3aabd823156e0d3fff1293dae843 [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000012 Only Tcl/Tk 8.2 and later are supported. Older versions are not
13 supported. (Use Python 2.2 if you cannot upgrade your Tcl/Tk
Guido van Rossuma80649b2000-03-28 20:07:05 +000014 libraries.)
15*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Martin v. Löwis39195712003-01-04 00:33:13 +000036/* Allow using this code in Python 2.[12] */
37#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000038#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000039#endif
40
41#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000042#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000045#ifndef PyBool_Check
46#define PyBool_Check(o) 0
47#define PyBool_FromLong PyInt_FromLong
48#endif
49
Martin v. Löwis71e25a02002-10-01 18:08:06 +000050/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
51 making _tkinter correct for this API means to break earlier
52 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
53 earlier versions. Once Tcl releases before 8.4 don't need to be supported
54 anymore, this should go. */
55#define USE_COMPAT_CONST
56
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000057/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
58 it always; if Tcl is not threaded, the thread functions in
59 Tcl are empty. */
60#define TCL_THREADS
61
Jack Jansencb852442001-12-09 23:15:56 +000062#ifdef TK_FRAMEWORK
63#include <Tcl/tcl.h>
64#include <Tk/tk.h>
65#else
Guido van Rossum18468821994-06-20 07:49:28 +000066#include <tcl.h>
67#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000068#endif
Guido van Rossum18468821994-06-20 07:49:28 +000069
Jason Tishlerbbe89612002-12-31 20:30:46 +000070/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000071#ifndef CONST84_RETURN
72#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000073#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000074#define CONST
75#endif
76
Guido van Rossum3e819a71997-08-01 19:29:02 +000077#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
78
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000079#if TKMAJORMINOR < 8002
80#error "Tk older than 8.2 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000081#endif
82
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000083/* Unicode conversion assumes that Tcl_UniChar is two bytes.
84 We cannot test this directly, so we test UTF-8 size instead,
85 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000086 either UTF-16 or UCS-4.
87 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
88 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
89 as well.
90*/
91#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000092#error "unsupported Tcl configuration"
93#endif
94
Jack Janseneddc1442003-11-20 01:44:59 +000095#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000096#define HAVE_CREATEFILEHANDLER
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#ifdef HAVE_CREATEFILEHANDLER
100
Neal Norwitzd948a432006-01-08 01:08:55 +0000101/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
102 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
103#ifndef TCL_UNIX_FD
104# ifdef TCL_WIN_SOCKET
105# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
106# else
107# define TCL_UNIX_FD 1
108# endif
109#endif
110
Guido van Rossum00d93061998-05-28 23:06:38 +0000111/* Tcl_CreateFileHandler() changed several times; these macros deal with the
112 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
113 Unix, only because Jack added it back); when available on Windows, it only
114 applies to sockets. */
115
Guido van Rossum7bf15641998-05-22 18:28:17 +0000116#ifdef MS_WINDOWS
117#define FHANDLETYPE TCL_WIN_SOCKET
118#else
119#define FHANDLETYPE TCL_UNIX_FD
120#endif
121
Guido van Rossum00d93061998-05-28 23:06:38 +0000122/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
123 which uses this to handle Tcl events while the user is typing commands. */
124
125#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000126#define WAIT_FOR_STDIN
127#endif
128
Guido van Rossum00d93061998-05-28 23:06:38 +0000129#endif /* HAVE_CREATEFILEHANDLER */
130
Guido van Rossumad4db171998-06-13 13:56:28 +0000131#ifdef MS_WINDOWS
132#include <conio.h>
133#define WAIT_FOR_STDIN
134#endif
135
Guido van Rossum00d93061998-05-28 23:06:38 +0000136#ifdef WITH_THREAD
137
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000138/* The threading situation is complicated. Tcl is not thread-safe, except
139 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000140 So we need to use a lock around all uses of Tcl. Previously, the Python
141 interpreter lock was used for this. However, this causes problems when
142 other Python threads need to run while Tcl is blocked waiting for events.
143
144 To solve this problem, a separate lock for Tcl is introduced. Holding it
145 is incompatible with holding Python's interpreter lock. The following four
146 macros manipulate both locks together.
147
148 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
149 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
150 that could call an event handler, or otherwise affect the state of a Tcl
151 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000152 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000153 released and the lock for Tcl has been acquired.
154
Guido van Rossum5e977831998-06-15 14:03:52 +0000155 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
156 (For example, when transferring data from the Tcl interpreter result to a
157 Python string object.) This can be done by using different macros to close
158 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
159 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
160 releases the Tcl lock.
161
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000162 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000163 handlers when the handler needs to use Python. Such event handlers are
164 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000165 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000166 the Python interpreter lock, restoring the appropriate thread state, and
167 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
168 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000169 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000170
171 These locks expand to several statements and brackets; they should not be
172 used in branches of if statements and the like.
173
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000174 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
175 only valid in the thread that created it, and all Tk activity must happen in this
176 thread, also. That means that the mainloop must be invoked in the thread that
177 created the interpreter. Invoking commands from other threads is possible;
178 _tkinter will queue an event for the interpreter thread, which will then
179 execute the command and pass back the result. If the main thread is not in the
180 mainloop, and invoking commands causes an exception; if the main loop is running
181 but not processing events, the command invocation will block.
182
183 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
184 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
185 threads. So we use the Tcl TLS API.
186
Guido van Rossum00d93061998-05-28 23:06:38 +0000187*/
188
Guido van Rossum65d5b571998-12-21 19:32:43 +0000189static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000190
191#ifdef TCL_THREADS
192static Tcl_ThreadDataKey state_key;
193typedef PyThreadState *ThreadSpecificData;
194#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
195#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000196static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000197#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000198
199#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000200 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000201 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
203#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000204 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000205
Guido van Rossum62320c91998-06-15 04:36:09 +0000206#define ENTER_OVERLAP \
207 Py_END_ALLOW_THREADS
208
209#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000210 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000211
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000212#define ENTER_PYTHON \
213 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000214 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
216#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000217 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000218 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
219
220#define CHECK_TCL_APPARTMENT \
221 if (((TkappObject *)self)->threaded && \
222 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
223 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
224 return 0; \
225 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000226
227#else
228
229#define ENTER_TCL
230#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000231#define ENTER_OVERLAP
232#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000233#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000234#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000235#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000236
237#endif
238
Guido van Rossum97867b21996-08-08 19:09:53 +0000239#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000240#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000241#endif
242
Guido van Rossum18468821994-06-20 07:49:28 +0000243/**** Tkapp Object Declaration ****/
244
Jeremy Hylton938ace62002-07-17 16:30:39 +0000245static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000246
Guido van Rossum00d93061998-05-28 23:06:38 +0000247typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000248 PyObject_HEAD
249 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000250 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000251 int threaded; /* True if tcl_platform[threaded] */
252 Tcl_ThreadId thread_id;
253 int dispatching;
254 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000255 So we cache interesting types here. */
256 Tcl_ObjType *BooleanType;
257 Tcl_ObjType *ByteArrayType;
258 Tcl_ObjType *DoubleType;
259 Tcl_ObjType *IntType;
260 Tcl_ObjType *ListType;
261 Tcl_ObjType *ProcBodyType;
262 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000263} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000264
265#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000266#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000267#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000268
Guido van Rossum35d43371997-08-02 00:09:09 +0000269#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000270(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000271
Barry Warsawfa701a81997-01-16 00:15:11 +0000272
273
Guido van Rossum18468821994-06-20 07:49:28 +0000274/**** Error Handling ****/
275
276static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000277static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000278static int errorInCmd = 0;
279static PyObject *excInCmd;
280static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000281static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
284
Guido van Rossum18468821994-06-20 07:49:28 +0000285static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000286Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000287{
Barry Warsawfa701a81997-01-16 00:15:11 +0000288 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
289 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000290}
291
Barry Warsawfa701a81997-01-16 00:15:11 +0000292
Barry Warsawfa701a81997-01-16 00:15:11 +0000293
Guido van Rossum18468821994-06-20 07:49:28 +0000294/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000295
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000296static int Tkinter_busywaitinterval = 20;
297
Guido van Rossum00d93061998-05-28 23:06:38 +0000298#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000299#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000300
Guido van Rossum00d93061998-05-28 23:06:38 +0000301/* Millisecond sleep() for Unix platforms. */
302
303static void
Fred Drake509d79a2000-07-08 04:04:38 +0000304Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000305{
306 /* XXX Too bad if you don't have select(). */
307 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000308 t.tv_sec = milli/1000;
309 t.tv_usec = (milli%1000) * 1000;
310 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
311}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000312#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000313
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000314/* Wait up to 1s for the mainloop to come up. */
315
316static int
317WaitForMainloop(TkappObject* self)
318{
319 int i;
320 for (i = 0; i < 10; i++) {
321 if (self->dispatching)
322 return 1;
323 Py_BEGIN_ALLOW_THREADS
324 Sleep(100);
325 Py_END_ALLOW_THREADS
326 }
327 if (self->dispatching)
328 return 1;
329 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
330 return 0;
331}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000332#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000333
Guido van Rossum00d93061998-05-28 23:06:38 +0000334
Guido van Rossum18468821994-06-20 07:49:28 +0000335static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000336AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000337{
Guido van Rossum35d43371997-08-02 00:09:09 +0000338 if (PyString_Check(value))
339 return PyString_AsString(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000340 else if (PyUnicode_Check(value)) {
341 PyObject *v = PyUnicode_AsUTF8String(value);
342 if (v == NULL)
343 return NULL;
344 if (PyList_Append(tmp, v) != 0) {
345 Py_DECREF(v);
346 return NULL;
347 }
348 Py_DECREF(v);
349 return PyString_AsString(v);
350 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000351 else {
352 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000353 if (v == NULL)
354 return NULL;
355 if (PyList_Append(tmp, v) != 0) {
356 Py_DECREF(v);
357 return NULL;
358 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000359 Py_DECREF(v);
360 return PyString_AsString(v);
361 }
Guido van Rossum18468821994-06-20 07:49:28 +0000362}
363
Barry Warsawfa701a81997-01-16 00:15:11 +0000364
365
Guido van Rossum18468821994-06-20 07:49:28 +0000366#define ARGSZ 64
367
368static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000369Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000370{
Barry Warsawfa701a81997-01-16 00:15:11 +0000371 PyObject *tmp = NULL;
372 char *argvStore[ARGSZ];
373 char **argv = NULL;
374 int fvStore[ARGSZ];
375 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000376 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000377 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000378
Barry Warsawfa701a81997-01-16 00:15:11 +0000379 if (!(tmp = PyList_New(0)))
380 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000381
Barry Warsawfa701a81997-01-16 00:15:11 +0000382 argv = argvStore;
383 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000384
Barry Warsawfa701a81997-01-16 00:15:11 +0000385 if (args == NULL)
386 argc = 0;
387
388 else if (!PyTuple_Check(args)) {
389 argc = 1;
390 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000391 if (!(argv[0] = AsString(args, tmp)))
392 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000393 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000394 else {
395 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000396
Barry Warsawfa701a81997-01-16 00:15:11 +0000397 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000398 argv = (char **)ckalloc(argc * sizeof(char *));
399 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000400 if (argv == NULL || fv == NULL) {
401 PyErr_NoMemory();
402 goto finally;
403 }
404 }
405
406 for (i = 0; i < argc; i++) {
407 PyObject *v = PyTuple_GetItem(args, i);
408 if (PyTuple_Check(v)) {
409 fv[i] = 1;
410 if (!(argv[i] = Merge(v)))
411 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000412 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000413 }
414 else if (v == Py_None) {
415 argc = i;
416 break;
417 }
418 else {
419 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000420 if (!(argv[i] = AsString(v, tmp)))
421 goto finally;
422 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000423 }
424 }
Guido van Rossum18468821994-06-20 07:49:28 +0000425 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000426 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000427 if (res == NULL)
428 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000429
Barry Warsawfa701a81997-01-16 00:15:11 +0000430 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000431 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000432 if (fv[i]) {
433 ckfree(argv[i]);
434 }
435 if (argv != argvStore)
436 ckfree(FREECAST argv);
437 if (fv != fvStore)
438 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000439
Barry Warsawfa701a81997-01-16 00:15:11 +0000440 Py_DECREF(tmp);
441 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000442}
443
Barry Warsawfa701a81997-01-16 00:15:11 +0000444
445
Guido van Rossum18468821994-06-20 07:49:28 +0000446static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000447Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000448{
Barry Warsawfa701a81997-01-16 00:15:11 +0000449 int argc;
450 char **argv;
451 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000452
Barry Warsawfa701a81997-01-16 00:15:11 +0000453 if (list == NULL) {
454 Py_INCREF(Py_None);
455 return Py_None;
456 }
Guido van Rossum18468821994-06-20 07:49:28 +0000457
Guido van Rossum00d93061998-05-28 23:06:38 +0000458 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000459 /* Not a list.
460 * Could be a quoted string containing funnies, e.g. {"}.
461 * Return the string itself.
462 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000463 return PyString_FromString(list);
464 }
Guido van Rossum18468821994-06-20 07:49:28 +0000465
Barry Warsawfa701a81997-01-16 00:15:11 +0000466 if (argc == 0)
467 v = PyString_FromString("");
468 else if (argc == 1)
469 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000470 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000471 int i;
472 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000473
Barry Warsawfa701a81997-01-16 00:15:11 +0000474 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000475 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000476 Py_DECREF(v);
477 v = NULL;
478 break;
479 }
480 PyTuple_SetItem(v, i, w);
481 }
482 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000483 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000484 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000485}
486
Martin v. Löwisffad6332002-11-26 09:28:05 +0000487/* In some cases, Tcl will still return strings that are supposed to be
488 lists. SplitObj walks through a nested tuple, finding string objects that
489 need to be split. */
490
491PyObject *
492SplitObj(PyObject *arg)
493{
494 if (PyTuple_Check(arg)) {
495 int i, size;
496 PyObject *elem, *newelem, *result;
497
498 size = PyTuple_Size(arg);
499 result = NULL;
500 /* Recursively invoke SplitObj for all tuple items.
501 If this does not return a new object, no action is
502 needed. */
503 for(i = 0; i < size; i++) {
504 elem = PyTuple_GetItem(arg, i);
505 newelem = SplitObj(elem);
506 if (!newelem) {
507 Py_XDECREF(result);
508 return NULL;
509 }
510 if (!result) {
511 int k;
512 if (newelem == elem) {
513 Py_DECREF(newelem);
514 continue;
515 }
516 result = PyTuple_New(size);
517 if (!result)
518 return NULL;
519 for(k = 0; k < i; k++) {
520 elem = PyTuple_GetItem(arg, k);
521 Py_INCREF(elem);
522 PyTuple_SetItem(result, k, elem);
523 }
524 }
525 PyTuple_SetItem(result, i, newelem);
526 }
527 if (result)
528 return result;
529 /* Fall through, returning arg. */
530 }
531 else if (PyString_Check(arg)) {
532 int argc;
533 char **argv;
534 char *list = PyString_AsString(arg);
535
536 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
537 Py_INCREF(arg);
538 return arg;
539 }
540 Tcl_Free(FREECAST argv);
541 if (argc > 1)
542 return Split(PyString_AsString(arg));
543 /* Fall through, returning arg. */
544 }
545 Py_INCREF(arg);
546 return arg;
547}
Barry Warsawfa701a81997-01-16 00:15:11 +0000548
549
Guido van Rossum18468821994-06-20 07:49:28 +0000550/**** Tkapp Object ****/
551
552#ifndef WITH_APPINIT
553int
Fred Drake509d79a2000-07-08 04:04:38 +0000554Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000555{
Barry Warsawfa701a81997-01-16 00:15:11 +0000556 Tk_Window main;
David Aschere2b4b322004-02-18 05:59:53 +0000557 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000558
Barry Warsawfa701a81997-01-16 00:15:11 +0000559 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000560 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000561 return TCL_ERROR;
562 }
David Aschere2b4b322004-02-18 05:59:53 +0000563 _tkinter_skip_tk_init = Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
564 if (_tkinter_skip_tk_init == NULL || strcmp(_tkinter_skip_tk_init, "1") != 0) {
565 main = Tk_MainWindow(interp);
566 if (Tk_Init(interp) == TCL_ERROR) {
567 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
568 return TCL_ERROR;
569 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000570 }
571 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000572}
573#endif /* !WITH_APPINIT */
574
Guido van Rossum18468821994-06-20 07:49:28 +0000575
Barry Warsawfa701a81997-01-16 00:15:11 +0000576
577
578/* Initialize the Tk application; see the `main' function in
579 * `tkMain.c'.
580 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000581
Thomas Wouters58d05102000-07-24 14:43:35 +0000582static void EnableEventHook(void); /* Forward */
583static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000584
Barry Warsawfa701a81997-01-16 00:15:11 +0000585static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000586Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000587 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000588{
589 TkappObject *v;
590 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000591
Guido van Rossumb18618d2000-05-03 23:44:39 +0000592 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000593 if (v == NULL)
594 return NULL;
595
596 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000597 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000598 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
599 TCL_GLOBAL_ONLY) != NULL;
600 v->thread_id = Tcl_GetCurrentThread();
601 v->dispatching = 0;
602
603#ifndef TCL_THREADS
604 if (v->threaded) {
605 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
606 Py_DECREF(v);
607 return 0;
608 }
609#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000610#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000611 if (v->threaded && tcl_lock) {
612 /* If Tcl is threaded, we don't need the lock. */
613 PyThread_free_lock(tcl_lock);
614 tcl_lock = NULL;
615 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000616#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000617
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000618 v->BooleanType = Tcl_GetObjType("boolean");
619 v->ByteArrayType = Tcl_GetObjType("bytearray");
620 v->DoubleType = Tcl_GetObjType("double");
621 v->IntType = Tcl_GetObjType("int");
622 v->ListType = Tcl_GetObjType("list");
623 v->ProcBodyType = Tcl_GetObjType("procbody");
624 v->StringType = Tcl_GetObjType("string");
625
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000626 /* Delete the 'exit' command, which can screw things up */
627 Tcl_DeleteCommand(v->interp, "exit");
628
Barry Warsawfa701a81997-01-16 00:15:11 +0000629 if (screenName != NULL)
630 Tcl_SetVar2(v->interp, "env", "DISPLAY",
631 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000632
Barry Warsawfa701a81997-01-16 00:15:11 +0000633 if (interactive)
634 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
635 else
636 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000637
Barry Warsawfa701a81997-01-16 00:15:11 +0000638 /* This is used to get the application class for Tk 4.1 and up */
639 argv0 = (char*)ckalloc(strlen(className) + 1);
640 if (!argv0) {
641 PyErr_NoMemory();
642 Py_DECREF(v);
643 return NULL;
644 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000645
Barry Warsawfa701a81997-01-16 00:15:11 +0000646 strcpy(argv0, className);
Neal Norwitz9dbc7dd2005-12-19 06:08:59 +0000647 if (isupper(Py_CHARMASK(argv0[0])))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000648 argv0[0] = tolower(Py_CHARMASK(argv0[0]));
Barry Warsawfa701a81997-01-16 00:15:11 +0000649 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
650 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000651
David Aschere2b4b322004-02-18 05:59:53 +0000652 if (! wantTk) {
653 Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
654 }
655
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000656 /* some initial arguments need to be in argv */
657 if (sync || use) {
Tim Peters51fa3b72004-08-04 02:16:48 +0000658 char *args;
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000659 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000660
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000661 if (sync)
662 len += sizeof "-sync";
663 if (use)
664 len += strlen(use) + sizeof "-use ";
665
Tim Peters51fa3b72004-08-04 02:16:48 +0000666 args = (char*)ckalloc(len);
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000667 if (!args) {
668 PyErr_NoMemory();
669 Py_DECREF(v);
670 return NULL;
671 }
672
673 args[0] = '\0';
674 if (sync)
675 strcat(args, "-sync");
676 if (use) {
677 if (sync)
678 strcat(args, " ");
679 strcat(args, "-use ");
680 strcat(args, use);
681 }
682
683 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
684 ckfree(args);
685 }
686
Thomas Woutersa74a84d2006-03-07 14:04:31 +0000687 if (Tcl_AppInit(v->interp) != TCL_OK) {
688 PyObject *result = Tkinter_Error((PyObject *)v);
689 Py_DECREF((PyObject *)v);
690 return (TkappObject *)result;
691 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000692
Guido van Rossum7bf15641998-05-22 18:28:17 +0000693 EnableEventHook();
694
Barry Warsawfa701a81997-01-16 00:15:11 +0000695 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000696}
697
Barry Warsawfa701a81997-01-16 00:15:11 +0000698
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000699static void
700Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
701 Tcl_Condition *cond, Tcl_Mutex *mutex)
702{
703 Py_BEGIN_ALLOW_THREADS;
704 Tcl_MutexLock(mutex);
705 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
706 Tcl_ThreadAlert(self->thread_id);
707 Tcl_ConditionWait(cond, mutex, NULL);
708 Tcl_MutexUnlock(mutex);
709 Py_END_ALLOW_THREADS
710}
711
Barry Warsawfa701a81997-01-16 00:15:11 +0000712
Guido van Rossum18468821994-06-20 07:49:28 +0000713/** Tcl Eval **/
714
Martin v. Löwisffad6332002-11-26 09:28:05 +0000715typedef struct {
716 PyObject_HEAD
717 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000718 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000719} PyTclObject;
720
Neal Norwitz227b5332006-03-22 09:28:35 +0000721static PyTypeObject PyTclObject_Type;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000722#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
723
724static PyObject *
725newPyTclObject(Tcl_Obj *arg)
726{
727 PyTclObject *self;
728 self = PyObject_New(PyTclObject, &PyTclObject_Type);
729 if (self == NULL)
730 return NULL;
731 Tcl_IncrRefCount(arg);
732 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000733 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000734 return (PyObject*)self;
735}
736
737static void
738PyTclObject_dealloc(PyTclObject *self)
739{
740 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000741 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000742 PyObject_Del(self);
743}
744
745static PyObject *
746PyTclObject_str(PyTclObject *self)
747{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000748 if (self->string && PyString_Check(self->string)) {
749 Py_INCREF(self->string);
750 return self->string;
751 }
752 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000753 return PyString_FromString(Tcl_GetString(self->value));
754}
755
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000756static char*
757PyTclObject_TclString(PyObject *self)
758{
759 return Tcl_GetString(((PyTclObject*)self)->value);
760}
761
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000762/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000763PyDoc_STRVAR(PyTclObject_string__doc__,
764"the string representation of this object, either as string or Unicode");
765
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000766static PyObject *
767PyTclObject_string(PyTclObject *self, void *ignored)
768{
769 char *s;
770 int i, len;
771 if (!self->string) {
772 s = Tcl_GetStringFromObj(self->value, &len);
773 for (i = 0; i < len; i++)
774 if (s[i] & 0x80)
775 break;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000776 if (i == len)
777 /* It is an ASCII string. */
778 self->string = PyString_FromStringAndSize(s, len);
779 else {
780 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
781 if (!self->string) {
782 PyErr_Clear();
783 self->string = PyString_FromStringAndSize(s, len);
784 }
785 }
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000786 if (!self->string)
787 return NULL;
788 }
789 Py_INCREF(self->string);
790 return self->string;
791}
792
Martin v. Löwis39195712003-01-04 00:33:13 +0000793PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
794
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000795static PyObject *
796PyTclObject_unicode(PyTclObject *self, void *ignored)
797{
798 char *s;
799 int len;
800 if (self->string && PyUnicode_Check(self->string)) {
801 Py_INCREF(self->string);
802 return self->string;
803 }
804 /* XXX Could chache result if it is non-ASCII. */
805 s = Tcl_GetStringFromObj(self->value, &len);
806 return PyUnicode_DecodeUTF8(s, len, "strict");
807}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000808
Martin v. Löwisffad6332002-11-26 09:28:05 +0000809static PyObject *
810PyTclObject_repr(PyTclObject *self)
811{
Walter Dörwald7569dfe2007-05-19 21:49:49 +0000812 return PyUnicode_FromFormat("<%s object at %p>",
813 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000814}
815
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000816static int
817PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
818{
819 int res;
820 res = strcmp(Tcl_GetString(self->value),
821 Tcl_GetString(other->value));
822 if (res < 0) return -1;
823 if (res > 0) return 1;
824 return 0;
825}
826
Martin v. Löwis39195712003-01-04 00:33:13 +0000827PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
828
Martin v. Löwisffad6332002-11-26 09:28:05 +0000829static PyObject*
830get_typename(PyTclObject* obj, void* ignored)
831{
832 return PyString_FromString(obj->value->typePtr->name);
833}
834
Martin v. Löwis39195712003-01-04 00:33:13 +0000835
Martin v. Löwisffad6332002-11-26 09:28:05 +0000836static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000837 {"typename", (getter)get_typename, NULL, get_typename__doc__},
838 {"string", (getter)PyTclObject_string, NULL,
839 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000840 {0},
841};
842
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000843static PyMethodDef PyTclObject_methods[] = {
844 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000845 PyTclObject_unicode__doc__},
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000846 {0}
847};
848
Neal Norwitz227b5332006-03-22 09:28:35 +0000849static PyTypeObject PyTclObject_Type = {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000850 PyObject_HEAD_INIT(NULL)
851 0, /*ob_size*/
852 "_tkinter.Tcl_Obj", /*tp_name*/
853 sizeof(PyTclObject), /*tp_basicsize*/
854 0, /*tp_itemsize*/
855 /* methods */
856 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
857 0, /*tp_print*/
858 0, /*tp_getattr*/
859 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000860 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000861 (reprfunc)PyTclObject_repr, /*tp_repr*/
862 0, /*tp_as_number*/
863 0, /*tp_as_sequence*/
864 0, /*tp_as_mapping*/
865 0, /*tp_hash*/
866 0, /*tp_call*/
867 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000868 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000869 0, /*tp_setattro*/
870 0, /*tp_as_buffer*/
871 Py_TPFLAGS_DEFAULT, /*tp_flags*/
872 0, /*tp_doc*/
873 0, /*tp_traverse*/
874 0, /*tp_clear*/
875 0, /*tp_richcompare*/
876 0, /*tp_weaklistoffset*/
877 0, /*tp_iter*/
878 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000879 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000880 0, /*tp_members*/
881 PyTclObject_getsetlist, /*tp_getset*/
882 0, /*tp_base*/
883 0, /*tp_dict*/
884 0, /*tp_descr_get*/
885 0, /*tp_descr_set*/
886 0, /*tp_dictoffset*/
887 0, /*tp_init*/
888 0, /*tp_alloc*/
889 0, /*tp_new*/
890 0, /*tp_free*/
891 0, /*tp_is_gc*/
892};
893
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000894static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000895AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000896{
897 Tcl_Obj *result;
898
899 if (PyString_Check(value))
900 return Tcl_NewStringObj(PyString_AS_STRING(value),
901 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000902 else if (PyBool_Check(value))
903 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossumddefaf32007-01-14 03:31:43 +0000904 else if (PyInt_CheckExact(value))
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000905 return Tcl_NewLongObj(PyInt_AS_LONG(value));
906 else if (PyFloat_Check(value))
907 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
908 else if (PyTuple_Check(value)) {
909 Tcl_Obj **argv = (Tcl_Obj**)
910 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
911 int i;
912 if(!argv)
913 return 0;
914 for(i=0;i<PyTuple_Size(value);i++)
915 argv[i] = AsObj(PyTuple_GetItem(value,i));
916 result = Tcl_NewListObj(PyTuple_Size(value), argv);
917 ckfree(FREECAST argv);
918 return result;
919 }
920 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000921 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000922 Py_ssize_t size = PyUnicode_GET_SIZE(value);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000923 /* This #ifdef assumes that Tcl uses UCS-2.
924 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000925#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000926 Tcl_UniChar *outbuf;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000927 Py_ssize_t i;
928 assert(size < size * sizeof(Tcl_UniChar));
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000929 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
930 if (!outbuf) {
931 PyErr_NoMemory();
932 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000933 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000934 for (i = 0; i < size; i++) {
935 if (inbuf[i] >= 0x10000) {
936 /* Tcl doesn't do UTF-16, yet. */
937 PyErr_SetString(PyExc_ValueError,
938 "unsupported character");
939 ckfree(FREECAST outbuf);
940 return NULL;
941 }
942 outbuf[i] = inbuf[i];
943 }
944 result = Tcl_NewUnicodeObj(outbuf, size);
945 ckfree(FREECAST outbuf);
946 return result;
947#else
948 return Tcl_NewUnicodeObj(inbuf, size);
949#endif
950
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000951 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000952 else if(PyTclObject_Check(value)) {
953 Tcl_Obj *v = ((PyTclObject*)value)->value;
954 Tcl_IncrRefCount(v);
955 return v;
956 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000957 else {
958 PyObject *v = PyObject_Str(value);
959 if (!v)
960 return 0;
961 result = AsObj(v);
962 Py_DECREF(v);
963 return result;
964 }
965}
966
Martin v. Löwisffad6332002-11-26 09:28:05 +0000967static PyObject*
968FromObj(PyObject* tkapp, Tcl_Obj *value)
969{
970 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000971 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000972
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000973 if (value->typePtr == NULL) {
974 /* If the result contains any bytes with the top bit set,
975 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000976 int i;
977 char *s = value->bytes;
978 int len = value->length;
979 for (i = 0; i < len; i++) {
980 if (value->bytes[i] & 0x80)
981 break;
982 }
983
984 if (i == value->length)
985 result = PyString_FromStringAndSize(s, len);
986 else {
987 /* Convert UTF-8 to Unicode string */
988 result = PyUnicode_DecodeUTF8(s, len, "strict");
989 if (result == NULL) {
990 PyErr_Clear();
991 result = PyString_FromStringAndSize(s, len);
992 }
993 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000994 return result;
995 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000996
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000997 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000998 result = value->internalRep.longValue ? Py_True : Py_False;
999 Py_INCREF(result);
1000 return result;
1001 }
1002
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001003 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001004 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +00001005 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001006 return PyString_FromStringAndSize(data, size);
1007 }
1008
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001009 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001010 return PyFloat_FromDouble(value->internalRep.doubleValue);
1011 }
1012
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001013 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001014 return PyInt_FromLong(value->internalRep.longValue);
1015 }
1016
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001017 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001018 int size;
1019 int i, status;
1020 PyObject *elem;
1021 Tcl_Obj *tcl_elem;
1022
1023 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1024 if (status == TCL_ERROR)
1025 return Tkinter_Error(tkapp);
1026 result = PyTuple_New(size);
1027 if (!result)
1028 return NULL;
1029 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001030 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001031 value, i, &tcl_elem);
1032 if (status == TCL_ERROR) {
1033 Py_DECREF(result);
1034 return Tkinter_Error(tkapp);
1035 }
1036 elem = FromObj(tkapp, tcl_elem);
1037 if (!elem) {
1038 Py_DECREF(result);
1039 return NULL;
1040 }
1041 PyTuple_SetItem(result, i, elem);
1042 }
1043 return result;
1044 }
1045
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001046 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001047 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001048 }
1049
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001050 if (value->typePtr == app->StringType) {
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001051#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001052 PyObject *result;
1053 int size;
1054 Tcl_UniChar *input;
1055 Py_UNICODE *output;
1056
1057 size = Tcl_GetCharLength(value);
1058 result = PyUnicode_FromUnicode(NULL, size);
1059 if (!result)
1060 return NULL;
1061 input = Tcl_GetUnicode(value);
1062 output = PyUnicode_AS_UNICODE(result);
1063 while (size--)
1064 *output++ = *input++;
1065 return result;
1066#else
1067 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1068 Tcl_GetCharLength(value));
1069#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +00001070 }
1071
1072 return newPyTclObject(value);
1073}
1074
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001075/* This mutex synchronizes inter-thread command calls. */
1076
1077TCL_DECLARE_MUTEX(call_mutex)
1078
1079typedef struct Tkapp_CallEvent {
1080 Tcl_Event ev; /* Must be first */
1081 TkappObject *self;
1082 PyObject *args;
1083 int flags;
1084 PyObject **res;
1085 PyObject **exc_type, **exc_value, **exc_tb;
1086 Tcl_Condition done;
1087} Tkapp_CallEvent;
1088
1089void
1090Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001091{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001092 int i;
1093 for (i = 0; i < objc; i++)
1094 Tcl_DecrRefCount(objv[i]);
1095 if (objv != objStore)
1096 ckfree(FREECAST objv);
1097}
Guido van Rossum18468821994-06-20 07:49:28 +00001098
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001099/* Convert Python objects to Tcl objects. This must happen in the
1100 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001101
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001102static Tcl_Obj**
1103Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1104{
1105 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001106 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001107 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001108 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001109
Guido van Rossum212643f1998-04-29 16:22:14 +00001110 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001111 objv[0] = AsObj(args);
1112 if (objv[0] == 0)
1113 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001114 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001115 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001116 }
1117 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001118 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001119
Guido van Rossum632de272000-03-29 00:19:50 +00001120 if (objc > ARGSZ) {
1121 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1122 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001123 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001124 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001125 goto finally;
1126 }
1127 }
1128
Guido van Rossum632de272000-03-29 00:19:50 +00001129 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001130 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001131 if (v == Py_None) {
1132 objc = i;
1133 break;
1134 }
Guido van Rossum632de272000-03-29 00:19:50 +00001135 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001136 if (!objv[i]) {
1137 /* Reset objc, so it attempts to clear
1138 objects only up to i. */
1139 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001140 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001141 }
Guido van Rossum632de272000-03-29 00:19:50 +00001142 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001143 }
1144 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001145 *pobjc = objc;
1146 return objv;
1147finally:
1148 Tkapp_CallDeallocArgs(objv, objStore, objc);
1149 return NULL;
1150}
Guido van Rossum212643f1998-04-29 16:22:14 +00001151
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001152/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001153
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001154static PyObject*
1155Tkapp_CallResult(TkappObject *self)
1156{
1157 PyObject *res = NULL;
1158 if(self->wantobjects) {
1159 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001160 /* Not sure whether the IncrRef is necessary, but something
1161 may overwrite the interpreter result while we are
1162 converting it. */
1163 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001164 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001165 Tcl_DecrRefCount(value);
1166 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001167 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001168 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001169
Guido van Rossum990f5c62000-05-04 15:07:16 +00001170 /* If the result contains any bytes with the top bit set,
1171 it's UTF-8 and we should decode it to Unicode */
1172 while (*p != '\0') {
1173 if (*p & 0x80)
1174 break;
1175 p++;
1176 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001177
Guido van Rossum990f5c62000-05-04 15:07:16 +00001178 if (*p == '\0')
1179 res = PyString_FromStringAndSize(s, (int)(p-s));
1180 else {
1181 /* Convert UTF-8 to Unicode string */
1182 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001183 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1184 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001185 PyErr_Clear();
1186 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001187 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001188 }
1189 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001190 return res;
1191}
Guido van Rossum632de272000-03-29 00:19:50 +00001192
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001193/* Tkapp_CallProc is the event procedure that is executed in the context of
1194 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1195 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001196
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001197static int
1198Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1199{
1200 Tcl_Obj *objStore[ARGSZ];
1201 Tcl_Obj **objv;
1202 int objc;
1203 int i;
1204 ENTER_PYTHON
1205 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1206 if (!objv) {
1207 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1208 *(e->res) = NULL;
1209 }
1210 LEAVE_PYTHON
1211 if (!objv)
1212 goto done;
1213 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1214 ENTER_PYTHON
1215 if (i == TCL_ERROR) {
1216 *(e->res) = NULL;
1217 *(e->exc_type) = NULL;
1218 *(e->exc_tb) = NULL;
1219 *(e->exc_value) = PyObject_CallFunction(
1220 Tkinter_TclError, "s",
1221 Tcl_GetStringResult(e->self->interp));
1222 }
1223 else {
1224 *(e->res) = Tkapp_CallResult(e->self);
1225 }
1226 LEAVE_PYTHON
1227 done:
1228 /* Wake up calling thread. */
1229 Tcl_MutexLock(&call_mutex);
1230 Tcl_ConditionNotify(&e->done);
1231 Tcl_MutexUnlock(&call_mutex);
1232 return 1;
1233}
1234
1235/* This is the main entry point for calling a Tcl command.
1236 It supports three cases, with regard to threading:
1237 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1238 the context of the calling thread.
1239 2. Tcl is threaded, caller of the command is in the interpreter thread:
1240 Execute the command in the calling thread. Since the Tcl lock will
1241 not be used, we can merge that with case 1.
1242 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1243 the interpreter thread. Allocation of Tcl objects needs to occur in the
1244 interpreter thread, so we ship the PyObject* args to the target thread,
1245 and perform processing there. */
1246
1247static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001248Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001249{
1250 Tcl_Obj *objStore[ARGSZ];
1251 Tcl_Obj **objv = NULL;
1252 int objc, i;
1253 PyObject *res = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001254 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001255 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1256 int flags = TCL_EVAL_DIRECT;
1257
Martin v. Löwisa9656492003-03-30 08:44:58 +00001258#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001259 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1260 /* We cannot call the command directly. Instead, we must
1261 marshal the parameters to the interpreter thread. */
1262 Tkapp_CallEvent *ev;
1263 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001264 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001265 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001266 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1267 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1268 ev->self = self;
1269 ev->args = args;
1270 ev->res = &res;
1271 ev->exc_type = &exc_type;
1272 ev->exc_value = &exc_value;
1273 ev->exc_tb = &exc_tb;
1274 ev->done = (Tcl_Condition)0;
1275
1276 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1277
1278 if (res == NULL) {
1279 if (exc_type)
1280 PyErr_Restore(exc_type, exc_value, exc_tb);
1281 else
1282 PyErr_SetObject(Tkinter_TclError, exc_value);
1283 }
1284 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001285 else
1286#endif
1287 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001288
1289 objv = Tkapp_CallArgs(args, objStore, &objc);
1290 if (!objv)
1291 return NULL;
1292
1293 ENTER_TCL
1294
1295 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1296
1297 ENTER_OVERLAP
1298
1299 if (i == TCL_ERROR)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001300 Tkinter_Error(selfptr);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001301 else
1302 res = Tkapp_CallResult(self);
1303
1304 LEAVE_OVERLAP_TCL
1305
1306 Tkapp_CallDeallocArgs(objv, objStore, objc);
1307 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001308 return res;
1309}
1310
1311
1312static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001313Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001314{
Guido van Rossum212643f1998-04-29 16:22:14 +00001315 /* Could do the same here as for Tkapp_Call(), but this is not used
1316 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1317 way for the user to do what all its Global* variants do (save and
1318 reset the scope pointer, call the local version, restore the saved
1319 scope pointer). */
1320
Guido van Rossum62320c91998-06-15 04:36:09 +00001321 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001322 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001323
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001324 CHECK_TCL_APPARTMENT;
1325
Guido van Rossum62320c91998-06-15 04:36:09 +00001326 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001327 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001328 int err;
1329 ENTER_TCL
1330 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001331 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001332 if (err == TCL_ERROR)
1333 res = Tkinter_Error(self);
1334 else
1335 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001336 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001337 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001338 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001339
1340 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001341}
1342
1343static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001344Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001345{
Barry Warsawfa701a81997-01-16 00:15:11 +00001346 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001347 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001348 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001349
Guido van Rossum43713e52000-02-29 13:59:29 +00001350 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001351 return NULL;
1352
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001353 CHECK_TCL_APPARTMENT;
1354
Guido van Rossum00d93061998-05-28 23:06:38 +00001355 ENTER_TCL
1356 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001357 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001358 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001359 res = Tkinter_Error(self);
1360 else
1361 res = PyString_FromString(Tkapp_Result(self));
1362 LEAVE_OVERLAP_TCL
1363 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001364}
1365
1366static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001367Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001368{
Barry Warsawfa701a81997-01-16 00:15:11 +00001369 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001370 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001371 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001372
Guido van Rossum43713e52000-02-29 13:59:29 +00001373 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001374 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001375
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001376 CHECK_TCL_APPARTMENT;
1377
Guido van Rossum00d93061998-05-28 23:06:38 +00001378 ENTER_TCL
1379 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001380 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001381 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001382 res = Tkinter_Error(self);
1383 else
1384 res = PyString_FromString(Tkapp_Result(self));
1385 LEAVE_OVERLAP_TCL
1386 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001387}
1388
1389static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001390Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001391{
Barry Warsawfa701a81997-01-16 00:15:11 +00001392 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001393 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001394 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001395
Guido van Rossum43713e52000-02-29 13:59:29 +00001396 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001397 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001398
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001399 CHECK_TCL_APPARTMENT;
1400
Guido van Rossum00d93061998-05-28 23:06:38 +00001401 ENTER_TCL
1402 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001403 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001404 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001405 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001406
Guido van Rossum62320c91998-06-15 04:36:09 +00001407 else
1408 res = PyString_FromString(Tkapp_Result(self));
1409 LEAVE_OVERLAP_TCL
1410 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001411}
1412
1413static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001414Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001415{
Barry Warsawfa701a81997-01-16 00:15:11 +00001416 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001417 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001418 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001419
Guido van Rossum35d43371997-08-02 00:09:09 +00001420 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001421 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001422
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001423 CHECK_TCL_APPARTMENT;
1424
Guido van Rossum00d93061998-05-28 23:06:38 +00001425 ENTER_TCL
1426 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001427 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001428 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001429 res = Tkinter_Error(self);
1430 else
1431 res = PyString_FromString(Tkapp_Result(self));
1432 LEAVE_OVERLAP_TCL
1433 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001434}
1435
1436static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001437Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001438{
Barry Warsawfa701a81997-01-16 00:15:11 +00001439 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001440
Guido van Rossum43713e52000-02-29 13:59:29 +00001441 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001442 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001443 CHECK_TCL_APPARTMENT;
1444
Guido van Rossum00d93061998-05-28 23:06:38 +00001445 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001446 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001447 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001448
Barry Warsawfa701a81997-01-16 00:15:11 +00001449 Py_INCREF(Py_None);
1450 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001451}
1452
Barry Warsawfa701a81997-01-16 00:15:11 +00001453
1454
Guido van Rossum18468821994-06-20 07:49:28 +00001455/** Tcl Variable **/
1456
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001457TCL_DECLARE_MUTEX(var_mutex)
1458
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001459typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001460typedef struct VarEvent {
1461 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001462 PyObject *self;
1463 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001464 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001465 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001466 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001467 PyObject **exc_type;
1468 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001469 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001470} VarEvent;
1471
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001472static int
1473varname_converter(PyObject *in, void *_out)
1474{
1475 char **out = (char**)_out;
1476 if (PyString_Check(in)) {
1477 *out = PyString_AsString(in);
1478 return 1;
1479 }
1480 if (PyTclObject_Check(in)) {
1481 *out = PyTclObject_TclString(in);
1482 return 1;
1483 }
1484 /* XXX: Should give diagnostics. */
1485 return 0;
1486}
1487
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001488void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001489var_perform(VarEvent *ev)
1490{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001491 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1492 if (!*(ev->res)) {
1493 PyObject *exc, *val, *tb;
1494 PyErr_Fetch(&exc, &val, &tb);
1495 PyErr_NormalizeException(&exc, &val, &tb);
1496 *(ev->exc_type) = exc;
1497 *(ev->exc_val) = val;
1498 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001499 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001500
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001501}
1502
1503static int
1504var_proc(VarEvent* ev, int flags)
1505{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001506 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001507 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001508 Tcl_MutexLock(&var_mutex);
1509 Tcl_ConditionNotify(&ev->cond);
1510 Tcl_MutexUnlock(&var_mutex);
1511 LEAVE_PYTHON
1512 return 1;
1513}
1514
1515static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001516var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001517{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001518 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001519#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001520 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001521 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001522 VarEvent *ev;
1523 PyObject *res, *exc_type, *exc_val;
1524
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001525 /* The current thread is not the interpreter thread. Marshal
1526 the call to the interpreter thread, then wait for
1527 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001528 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001529 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001530
1531 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1532
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001533 ev->self = selfptr;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001534 ev->args = args;
1535 ev->flags = flags;
1536 ev->func = func;
1537 ev->res = &res;
1538 ev->exc_type = &exc_type;
1539 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001540 ev->cond = NULL;
1541 ev->ev.proc = (Tcl_EventProc*)var_proc;
1542 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001543 if (!res) {
1544 PyErr_SetObject(exc_type, exc_val);
1545 Py_DECREF(exc_type);
1546 Py_DECREF(exc_val);
1547 return NULL;
1548 }
1549 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001550 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001551#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001552 /* Tcl is not threaded, or this is the interpreter thread. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001553 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001554}
1555
Guido van Rossum18468821994-06-20 07:49:28 +00001556static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001557SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001558{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001559 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001560 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001561 PyObject *res = NULL;
1562 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001563
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001564 if (PyArg_ParseTuple(args, "O&O:setvar",
1565 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001566 /* XXX Acquire tcl lock??? */
1567 newval = AsObj(newValue);
1568 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001569 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001570 ENTER_TCL
1571 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1572 newval, flags);
1573 ENTER_OVERLAP
1574 if (!ok)
1575 Tkinter_Error(self);
1576 else {
1577 res = Py_None;
1578 Py_INCREF(res);
1579 }
1580 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001581 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001582 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001583 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001584 if (PyArg_ParseTuple(args, "ssO:setvar",
1585 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001586 /* XXX must hold tcl lock already??? */
1587 newval = AsObj(newValue);
1588 ENTER_TCL
1589 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1590 ENTER_OVERLAP
1591 if (!ok)
1592 Tkinter_Error(self);
1593 else {
1594 res = Py_None;
1595 Py_INCREF(res);
1596 }
1597 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001598 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001599 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001600 return NULL;
1601 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001602 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001603 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001604}
1605
1606static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001607Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001608{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001609 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001610}
1611
1612static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001613Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001614{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001615 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001616}
1617
Barry Warsawfa701a81997-01-16 00:15:11 +00001618
1619
Guido van Rossum18468821994-06-20 07:49:28 +00001620static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001621GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001622{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001623 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001624 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001625 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001626
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001627 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1628 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001629 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001630
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001631 ENTER_TCL
1632 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1633 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001634 if (tres == NULL) {
1635 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1636 } else {
1637 if (((TkappObject*)self)->wantobjects) {
1638 res = FromObj(self, tres);
1639 }
1640 else {
1641 res = PyString_FromString(Tcl_GetString(tres));
1642 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001643 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001644 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001645 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001646}
1647
1648static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001649Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001650{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001651 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001652}
1653
1654static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001655Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001656{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001657 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001658}
1659
Barry Warsawfa701a81997-01-16 00:15:11 +00001660
1661
Guido van Rossum18468821994-06-20 07:49:28 +00001662static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001663UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001664{
Guido van Rossum35d43371997-08-02 00:09:09 +00001665 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001666 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001667 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001668
Guido van Rossum43713e52000-02-29 13:59:29 +00001669 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001670 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001671
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001672 ENTER_TCL
1673 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1674 ENTER_OVERLAP
1675 if (code == TCL_ERROR)
1676 res = Tkinter_Error(self);
1677 else {
1678 Py_INCREF(Py_None);
1679 res = Py_None;
1680 }
1681 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001682 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001683}
1684
1685static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001686Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001687{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001688 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001689}
1690
1691static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001692Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001693{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001694 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001695}
1696
Barry Warsawfa701a81997-01-16 00:15:11 +00001697
1698
Guido van Rossum18468821994-06-20 07:49:28 +00001699/** Tcl to Python **/
1700
1701static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001702Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001703{
Barry Warsawfa701a81997-01-16 00:15:11 +00001704 char *s;
1705 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001706
Martin v. Löwisffad6332002-11-26 09:28:05 +00001707 if (PyTuple_Size(args) == 1) {
1708 PyObject* o = PyTuple_GetItem(args, 0);
1709 if (PyInt_Check(o)) {
1710 Py_INCREF(o);
1711 return o;
1712 }
1713 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001714 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001715 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001716 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001717 return Tkinter_Error(self);
1718 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001719}
1720
1721static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001722Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001723{
Barry Warsawfa701a81997-01-16 00:15:11 +00001724 char *s;
1725 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001726
Martin v. Löwisffad6332002-11-26 09:28:05 +00001727 if (PyTuple_Size(args) == 1) {
1728 PyObject *o = PyTuple_GetItem(args, 0);
1729 if (PyFloat_Check(o)) {
1730 Py_INCREF(o);
1731 return o;
1732 }
1733 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001734 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001735 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001736 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001737 return Tkinter_Error(self);
1738 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001739}
1740
1741static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001742Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001743{
Barry Warsawfa701a81997-01-16 00:15:11 +00001744 char *s;
1745 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001746
Martin v. Löwisffad6332002-11-26 09:28:05 +00001747 if (PyTuple_Size(args) == 1) {
1748 PyObject *o = PyTuple_GetItem(args, 0);
1749 if (PyInt_Check(o)) {
1750 Py_INCREF(o);
1751 return o;
1752 }
1753 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001754 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001755 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001756 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1757 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001758 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001759}
1760
1761static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001762Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001763{
Barry Warsawfa701a81997-01-16 00:15:11 +00001764 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001765 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001766 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001767
Guido van Rossum43713e52000-02-29 13:59:29 +00001768 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001769 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001770
1771 CHECK_TCL_APPARTMENT;
1772
Guido van Rossum00d93061998-05-28 23:06:38 +00001773 ENTER_TCL
1774 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001775 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001776 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001777 res = Tkinter_Error(self);
1778 else
1779 res = Py_BuildValue("s", Tkapp_Result(self));
1780 LEAVE_OVERLAP_TCL
1781 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001782}
1783
1784static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001785Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001786{
Barry Warsawfa701a81997-01-16 00:15:11 +00001787 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001788 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001789 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001790 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001791
Guido van Rossum43713e52000-02-29 13:59:29 +00001792 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001793 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001794
1795 CHECK_TCL_APPARTMENT;
1796
Guido van Rossum00d93061998-05-28 23:06:38 +00001797 ENTER_TCL
1798 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001799 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001800 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001801 res = Tkinter_Error(self);
1802 else
1803 res = Py_BuildValue("l", v);
1804 LEAVE_OVERLAP_TCL
1805 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001806}
1807
1808static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001809Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001810{
Barry Warsawfa701a81997-01-16 00:15:11 +00001811 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001812 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001813 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001814 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001815
Guido van Rossum43713e52000-02-29 13:59:29 +00001816 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001817 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001818 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001819 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001820 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001821 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001822 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001823 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001824 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001825 res = Tkinter_Error(self);
1826 else
1827 res = Py_BuildValue("d", v);
1828 LEAVE_OVERLAP_TCL
1829 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001830}
1831
1832static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001833Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001834{
Barry Warsawfa701a81997-01-16 00:15:11 +00001835 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001836 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001837 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001838 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001839
Guido van Rossum43713e52000-02-29 13:59:29 +00001840 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001841 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001842 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001843 ENTER_TCL
1844 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001845 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001846 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001847 res = Tkinter_Error(self);
1848 else
1849 res = Py_BuildValue("i", v);
1850 LEAVE_OVERLAP_TCL
1851 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001852}
1853
Barry Warsawfa701a81997-01-16 00:15:11 +00001854
1855
Guido van Rossum18468821994-06-20 07:49:28 +00001856static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001857Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001858{
Barry Warsawfa701a81997-01-16 00:15:11 +00001859 char *list;
1860 int argc;
1861 char **argv;
1862 PyObject *v;
1863 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001864
Martin v. Löwisffad6332002-11-26 09:28:05 +00001865 if (PyTuple_Size(args) == 1) {
1866 v = PyTuple_GetItem(args, 0);
1867 if (PyTuple_Check(v)) {
1868 Py_INCREF(v);
1869 return v;
1870 }
1871 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001872 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001873 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001874
Neal Norwitzd1c55102003-05-29 00:17:03 +00001875 if (Tcl_SplitList(Tkapp_Interp(self), list,
1876 &argc, &argv) == TCL_ERROR) {
1877 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001878 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001879 }
Guido van Rossum18468821994-06-20 07:49:28 +00001880
Barry Warsawfa701a81997-01-16 00:15:11 +00001881 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001882 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001883
Barry Warsawfa701a81997-01-16 00:15:11 +00001884 for (i = 0; i < argc; i++) {
1885 PyObject *s = PyString_FromString(argv[i]);
1886 if (!s || PyTuple_SetItem(v, i, s)) {
1887 Py_DECREF(v);
1888 v = NULL;
1889 goto finally;
1890 }
1891 }
Guido van Rossum18468821994-06-20 07:49:28 +00001892
Barry Warsawfa701a81997-01-16 00:15:11 +00001893 finally:
1894 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001895 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001896 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001897}
1898
1899static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001900Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001901{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001902 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001903 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001904
Martin v. Löwisffad6332002-11-26 09:28:05 +00001905 if (PyTuple_Size(args) == 1) {
1906 PyObject* o = PyTuple_GetItem(args, 0);
1907 if (PyTuple_Check(o)) {
1908 o = SplitObj(o);
1909 return o;
1910 }
1911 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001912 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001913 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001914 v = Split(list);
1915 PyMem_Free(list);
1916 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001917}
1918
1919static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001920Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001921{
Barry Warsawfa701a81997-01-16 00:15:11 +00001922 char *s = Merge(args);
1923 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001924
Barry Warsawfa701a81997-01-16 00:15:11 +00001925 if (s) {
1926 res = PyString_FromString(s);
1927 ckfree(s);
1928 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001929
1930 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001931}
1932
Barry Warsawfa701a81997-01-16 00:15:11 +00001933
1934
Guido van Rossum18468821994-06-20 07:49:28 +00001935/** Tcl Command **/
1936
Guido van Rossum00d93061998-05-28 23:06:38 +00001937/* Client data struct */
1938typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001939 PyObject *self;
1940 PyObject *func;
1941} PythonCmd_ClientData;
1942
1943static int
Fred Drake509d79a2000-07-08 04:04:38 +00001944PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001945{
1946 errorInCmd = 1;
1947 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1948 LEAVE_PYTHON
1949 return TCL_ERROR;
1950}
1951
Guido van Rossum18468821994-06-20 07:49:28 +00001952/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001953 * function or method.
1954 */
Guido van Rossum18468821994-06-20 07:49:28 +00001955static int
Fred Drake509d79a2000-07-08 04:04:38 +00001956PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001957{
Guido van Rossum00d93061998-05-28 23:06:38 +00001958 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001959 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001960 int i, rv;
1961 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001962
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001963 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001964
Barry Warsawfa701a81997-01-16 00:15:11 +00001965 /* TBD: no error checking here since we know, via the
1966 * Tkapp_CreateCommand() that the client data is a two-tuple
1967 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001968 self = data->self;
1969 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001970
Barry Warsawfa701a81997-01-16 00:15:11 +00001971 /* Create argument list (argv1, ..., argvN) */
1972 if (!(arg = PyTuple_New(argc - 1)))
1973 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001974
Barry Warsawfa701a81997-01-16 00:15:11 +00001975 for (i = 0; i < (argc - 1); i++) {
1976 PyObject *s = PyString_FromString(argv[i + 1]);
1977 if (!s || PyTuple_SetItem(arg, i, s)) {
1978 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001979 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001980 }
1981 }
1982 res = PyEval_CallObject(func, arg);
1983 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001984
Barry Warsawfa701a81997-01-16 00:15:11 +00001985 if (res == NULL)
1986 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001987
Barry Warsawfa701a81997-01-16 00:15:11 +00001988 if (!(tmp = PyList_New(0))) {
1989 Py_DECREF(res);
1990 return PythonCmd_Error(interp);
1991 }
1992
Guido van Rossum2834b972000-10-06 16:58:26 +00001993 s = AsString(res, tmp);
1994 if (s == NULL) {
1995 rv = PythonCmd_Error(interp);
1996 }
1997 else {
1998 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1999 rv = TCL_OK;
2000 }
2001
Barry Warsawfa701a81997-01-16 00:15:11 +00002002 Py_DECREF(res);
2003 Py_DECREF(tmp);
2004
Guido van Rossum00d93061998-05-28 23:06:38 +00002005 LEAVE_PYTHON
2006
Guido van Rossum2834b972000-10-06 16:58:26 +00002007 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002008}
2009
2010static void
Fred Drake509d79a2000-07-08 04:04:38 +00002011PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002012{
Guido van Rossum00d93061998-05-28 23:06:38 +00002013 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2014
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002015 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002016 Py_XDECREF(data->self);
2017 Py_XDECREF(data->func);
2018 PyMem_DEL(data);
2019 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002020}
2021
Barry Warsawfa701a81997-01-16 00:15:11 +00002022
2023
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002024
2025TCL_DECLARE_MUTEX(command_mutex)
2026
2027typedef struct CommandEvent{
2028 Tcl_Event ev;
2029 Tcl_Interp* interp;
2030 char *name;
2031 int create;
2032 int *status;
2033 ClientData *data;
2034 Tcl_Condition done;
2035} CommandEvent;
2036
2037static int
2038Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002039{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002040 if (ev->create)
2041 *ev->status = Tcl_CreateCommand(
2042 ev->interp, ev->name, PythonCmd,
2043 ev->data, PythonCmdDelete) == NULL;
2044 else
2045 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2046 Tcl_MutexLock(&command_mutex);
2047 Tcl_ConditionNotify(&ev->done);
2048 Tcl_MutexUnlock(&command_mutex);
2049 return 1;
2050}
2051
2052static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002053Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002054{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002055 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002056 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002057 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002058 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002059 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002060
Guido van Rossum43713e52000-02-29 13:59:29 +00002061 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002062 return NULL;
2063 if (!PyCallable_Check(func)) {
2064 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002065 return NULL;
2066 }
Guido van Rossum18468821994-06-20 07:49:28 +00002067
Martin v. Löwisa9656492003-03-30 08:44:58 +00002068#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002069 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002070 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002071 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002072#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002073
Guido van Rossum00d93061998-05-28 23:06:38 +00002074 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002075 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002076 return PyErr_NoMemory();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002077 Py_INCREF(self);
2078 Py_INCREF(func);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002079 data->self = selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002080 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002081
2082 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2083 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2084 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2085 ev->interp = self->interp;
2086 ev->create = 1;
2087 ev->name = cmdName;
2088 ev->data = (ClientData)data;
2089 ev->status = &err;
2090 ev->done = NULL;
2091 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2092 }
2093 else {
2094 ENTER_TCL
2095 err = Tcl_CreateCommand(
2096 Tkapp_Interp(self), cmdName, PythonCmd,
2097 (ClientData)data, PythonCmdDelete) == NULL;
2098 LEAVE_TCL
2099 }
2100 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002101 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002102 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002103 return NULL;
2104 }
Guido van Rossum18468821994-06-20 07:49:28 +00002105
Barry Warsawfa701a81997-01-16 00:15:11 +00002106 Py_INCREF(Py_None);
2107 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002108}
2109
Barry Warsawfa701a81997-01-16 00:15:11 +00002110
2111
Guido van Rossum18468821994-06-20 07:49:28 +00002112static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002113Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002114{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002115 TkappObject *self = (TkappObject*)selfptr;
Barry Warsawfa701a81997-01-16 00:15:11 +00002116 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002117 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002118
Guido van Rossum43713e52000-02-29 13:59:29 +00002119 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002120 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002121 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2122 CommandEvent *ev;
2123 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2124 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2125 ev->interp = self->interp;
2126 ev->create = 0;
2127 ev->name = cmdName;
2128 ev->status = &err;
2129 ev->done = NULL;
2130 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2131 &command_mutex);
2132 }
2133 else {
2134 ENTER_TCL
2135 err = Tcl_DeleteCommand(self->interp, cmdName);
2136 LEAVE_TCL
2137 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002138 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002139 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2140 return NULL;
2141 }
2142 Py_INCREF(Py_None);
2143 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002144}
2145
Barry Warsawfa701a81997-01-16 00:15:11 +00002146
2147
Guido van Rossum00d93061998-05-28 23:06:38 +00002148#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002149/** File Handler **/
2150
Guido van Rossum00d93061998-05-28 23:06:38 +00002151typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002152 PyObject *func;
2153 PyObject *file;
2154 int id;
2155 struct _fhcdata *next;
2156} FileHandler_ClientData;
2157
2158static FileHandler_ClientData *HeadFHCD;
2159
2160static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002161NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002162{
2163 FileHandler_ClientData *p;
2164 p = PyMem_NEW(FileHandler_ClientData, 1);
2165 if (p != NULL) {
2166 Py_XINCREF(func);
2167 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002168 p->func = func;
2169 p->file = file;
2170 p->id = id;
2171 p->next = HeadFHCD;
2172 HeadFHCD = p;
2173 }
2174 return p;
2175}
2176
2177static void
Fred Drake509d79a2000-07-08 04:04:38 +00002178DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002179{
2180 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002181
2182 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002183 while ((p = *pp) != NULL) {
2184 if (p->id == id) {
2185 *pp = p->next;
2186 Py_XDECREF(p->func);
2187 Py_XDECREF(p->file);
2188 PyMem_DEL(p);
2189 }
2190 else
2191 pp = &p->next;
2192 }
2193}
2194
Guido van Rossuma597dde1995-01-10 20:56:29 +00002195static void
Fred Drake509d79a2000-07-08 04:04:38 +00002196FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002197{
Guido van Rossum00d93061998-05-28 23:06:38 +00002198 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002199 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002200
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002201 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002202 func = data->func;
2203 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002204
Barry Warsawfa701a81997-01-16 00:15:11 +00002205 arg = Py_BuildValue("(Oi)", file, (long) mask);
2206 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002207 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002208
2209 if (res == NULL) {
2210 errorInCmd = 1;
2211 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2212 }
2213 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002214 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002215}
2216
Guido van Rossum18468821994-06-20 07:49:28 +00002217static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002218Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2219 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002220{
Guido van Rossum00d93061998-05-28 23:06:38 +00002221 FileHandler_ClientData *data;
2222 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002223 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002224
Guido van Rossum2834b972000-10-06 16:58:26 +00002225 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2226 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002227 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002228
Martin v. Löwisa9656492003-03-30 08:44:58 +00002229#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002230 if (!self && !tcl_lock) {
2231 /* We don't have the Tcl lock since Tcl is threaded. */
2232 PyErr_SetString(PyExc_RuntimeError,
2233 "_tkinter.createfilehandler not supported "
2234 "for threaded Tcl");
2235 return NULL;
2236 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002237#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002238
2239 if (self) {
2240 CHECK_TCL_APPARTMENT;
2241 }
2242
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002243 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002244 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002245 return NULL;
2246 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002247 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002248 return NULL;
2249 }
2250
Guido van Rossuma80649b2000-03-28 20:07:05 +00002251 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002252 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002253 return NULL;
2254
Barry Warsawfa701a81997-01-16 00:15:11 +00002255 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002256 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002257 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002258 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002259 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002260 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002261}
2262
2263static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002264Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002265{
Barry Warsawfa701a81997-01-16 00:15:11 +00002266 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002267 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002268
Guido van Rossum43713e52000-02-29 13:59:29 +00002269 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002270 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002271
Martin v. Löwisa9656492003-03-30 08:44:58 +00002272#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002273 if (!self && !tcl_lock) {
2274 /* We don't have the Tcl lock since Tcl is threaded. */
2275 PyErr_SetString(PyExc_RuntimeError,
2276 "_tkinter.deletefilehandler not supported "
2277 "for threaded Tcl");
2278 return NULL;
2279 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002280#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002281
2282 if (self) {
2283 CHECK_TCL_APPARTMENT;
2284 }
2285
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002286 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002287 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002288 return NULL;
2289
Guido van Rossuma80649b2000-03-28 20:07:05 +00002290 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002291
Barry Warsawfa701a81997-01-16 00:15:11 +00002292 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002293 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002294 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002295 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002296 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002297 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002298}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002299#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002300
Barry Warsawfa701a81997-01-16 00:15:11 +00002301
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002302/**** Tktt Object (timer token) ****/
2303
Jeremy Hylton938ace62002-07-17 16:30:39 +00002304static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002305
Guido van Rossum00d93061998-05-28 23:06:38 +00002306typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002307 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002308 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002309 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002310} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002311
2312static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002313Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002314{
Barry Warsawfa701a81997-01-16 00:15:11 +00002315 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002316 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002317
Guido van Rossum43713e52000-02-29 13:59:29 +00002318 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002319 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002320 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002321 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002322 v->token = NULL;
2323 }
2324 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002325 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002326 Py_DECREF(func);
2327 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002328 }
2329 Py_INCREF(Py_None);
2330 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002331}
2332
2333static PyMethodDef Tktt_methods[] =
2334{
Neal Norwitzb0493252002-03-31 14:44:22 +00002335 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002336 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002337};
2338
2339static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002340Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002341{
Barry Warsawfa701a81997-01-16 00:15:11 +00002342 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002343
Guido van Rossumb18618d2000-05-03 23:44:39 +00002344 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002345 if (v == NULL)
2346 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002347
Guido van Rossum00d93061998-05-28 23:06:38 +00002348 Py_INCREF(func);
2349 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002350 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002351
2352 /* Extra reference, deleted when called or when handler is deleted */
2353 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002354 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002355}
2356
2357static void
Fred Drake509d79a2000-07-08 04:04:38 +00002358Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002359{
Guido van Rossum00d93061998-05-28 23:06:38 +00002360 TkttObject *v = (TkttObject *)self;
2361 PyObject *func = v->func;
2362
2363 Py_XDECREF(func);
2364
Guido van Rossumb18618d2000-05-03 23:44:39 +00002365 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002366}
2367
Guido van Rossum597ac201998-05-12 14:36:19 +00002368static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002369Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002370{
Barry Warsawfa701a81997-01-16 00:15:11 +00002371 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002372 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002373
Tim Peters885d4572001-11-28 20:27:42 +00002374 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002375 v->func == NULL ? ", handler deleted" : "");
Walter Dörwald1ab83302007-05-18 17:15:44 +00002376 return PyUnicode_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002377}
2378
2379static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002380Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002381{
Barry Warsawfa701a81997-01-16 00:15:11 +00002382 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002383}
2384
2385static PyTypeObject Tktt_Type =
2386{
Guido van Rossum35d43371997-08-02 00:09:09 +00002387 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002388 0, /*ob_size */
2389 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002390 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002391 0, /*tp_itemsize */
2392 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002393 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002394 Tktt_GetAttr, /*tp_getattr */
2395 0, /*tp_setattr */
2396 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002397 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002398 0, /*tp_as_number */
2399 0, /*tp_as_sequence */
2400 0, /*tp_as_mapping */
2401 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002402};
2403
Barry Warsawfa701a81997-01-16 00:15:11 +00002404
2405
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002406/** Timer Handler **/
2407
2408static void
Fred Drake509d79a2000-07-08 04:04:38 +00002409TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002410{
Guido van Rossum00d93061998-05-28 23:06:38 +00002411 TkttObject *v = (TkttObject *)clientData;
2412 PyObject *func = v->func;
2413 PyObject *res;
2414
2415 if (func == NULL)
2416 return;
2417
2418 v->func = NULL;
2419
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002420 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002421
2422 res = PyEval_CallObject(func, NULL);
2423 Py_DECREF(func);
2424 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002425
Barry Warsawfa701a81997-01-16 00:15:11 +00002426 if (res == NULL) {
2427 errorInCmd = 1;
2428 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2429 }
2430 else
2431 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002432
2433 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002434}
2435
2436static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002437Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002438{
Barry Warsawfa701a81997-01-16 00:15:11 +00002439 int milliseconds;
2440 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002441 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002442
Guido van Rossum2834b972000-10-06 16:58:26 +00002443 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2444 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002445 return NULL;
2446 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002447 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002448 return NULL;
2449 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002450
Martin v. Löwisa9656492003-03-30 08:44:58 +00002451#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002452 if (!self && !tcl_lock) {
2453 /* We don't have the Tcl lock since Tcl is threaded. */
2454 PyErr_SetString(PyExc_RuntimeError,
2455 "_tkinter.createtimerhandler not supported "
2456 "for threaded Tcl");
2457 return NULL;
2458 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002459#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002460
2461 if (self) {
2462 CHECK_TCL_APPARTMENT;
2463 }
2464
Guido van Rossum00d93061998-05-28 23:06:38 +00002465 v = Tktt_New(func);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002466 if (v) {
2467 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2468 (ClientData)v);
2469 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002470
Guido van Rossum00d93061998-05-28 23:06:38 +00002471 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002472}
2473
Barry Warsawfa701a81997-01-16 00:15:11 +00002474
Guido van Rossum18468821994-06-20 07:49:28 +00002475/** Event Loop **/
2476
Guido van Rossum18468821994-06-20 07:49:28 +00002477static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002478Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002479{
Barry Warsawfa701a81997-01-16 00:15:11 +00002480 int threshold = 0;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002481 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002482#ifdef WITH_THREAD
2483 PyThreadState *tstate = PyThreadState_Get();
2484#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002485
Guido van Rossum43713e52000-02-29 13:59:29 +00002486 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002487 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002488
Martin v. Löwisa9656492003-03-30 08:44:58 +00002489#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002490 if (!self && !tcl_lock) {
2491 /* We don't have the Tcl lock since Tcl is threaded. */
2492 PyErr_SetString(PyExc_RuntimeError,
2493 "_tkinter.mainloop not supported "
2494 "for threaded Tcl");
2495 return NULL;
2496 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002497#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002498
2499 if (self) {
2500 CHECK_TCL_APPARTMENT;
2501 self->dispatching = 1;
2502 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002503
Barry Warsawfa701a81997-01-16 00:15:11 +00002504 quitMainLoop = 0;
2505 while (Tk_GetNumMainWindows() > threshold &&
2506 !quitMainLoop &&
2507 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002508 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002509 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002510
2511#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002512 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002513 /* Allow other Python threads to run. */
2514 ENTER_TCL
2515 result = Tcl_DoOneEvent(0);
2516 LEAVE_TCL
2517 }
2518 else {
2519 Py_BEGIN_ALLOW_THREADS
2520 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2521 tcl_tstate = tstate;
2522 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2523 tcl_tstate = NULL;
2524 if(tcl_lock)PyThread_release_lock(tcl_lock);
2525 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002526 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002527 Py_END_ALLOW_THREADS
2528 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002529#else
2530 result = Tcl_DoOneEvent(0);
2531#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002532
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002533 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002534 if (self)
2535 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002536 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002537 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002538 if (result < 0)
2539 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002540 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002541 if (self)
2542 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002543 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002544
Barry Warsawfa701a81997-01-16 00:15:11 +00002545 if (errorInCmd) {
2546 errorInCmd = 0;
2547 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2548 excInCmd = valInCmd = trbInCmd = NULL;
2549 return NULL;
2550 }
2551 Py_INCREF(Py_None);
2552 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002553}
2554
2555static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002556Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002557{
Guido van Rossum35d43371997-08-02 00:09:09 +00002558 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002559 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002560
Guido van Rossum43713e52000-02-29 13:59:29 +00002561 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002562 return NULL;
2563
Guido van Rossum00d93061998-05-28 23:06:38 +00002564 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002565 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002566 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002567 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002568}
2569
2570static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002571Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002572{
2573
Guido van Rossum43713e52000-02-29 13:59:29 +00002574 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002575 return NULL;
2576
2577 quitMainLoop = 1;
2578 Py_INCREF(Py_None);
2579 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002580}
2581
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002582static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002583Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002584{
2585
Guido van Rossum43713e52000-02-29 13:59:29 +00002586 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002587 return NULL;
2588
2589 return PyInt_FromLong((long)Tkapp_Interp(self));
2590}
2591
David Aschere2b4b322004-02-18 05:59:53 +00002592static PyObject *
2593Tkapp_TkInit(PyObject *self, PyObject *args)
2594{
Thomas Wouters477c8d52006-05-27 19:21:47 +00002595 static int has_failed;
David Aschere2b4b322004-02-18 05:59:53 +00002596 Tcl_Interp *interp = Tkapp_Interp(self);
Neal Norwitz44dbae82004-02-19 02:44:22 +00002597 Tk_Window main_window;
David Aschere2b4b322004-02-18 05:59:53 +00002598 const char * _tk_exists = NULL;
David Aschere2b4b322004-02-18 05:59:53 +00002599 int err;
Neal Norwitz44dbae82004-02-19 02:44:22 +00002600 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002601
Thomas Wouters477c8d52006-05-27 19:21:47 +00002602 /* In all current versions of Tk (including 8.4.13), Tk_Init
2603 deadlocks on the second call when the first call failed.
2604 To avoid the deadlock, we just refuse the second call through
2605 a static variable. */
2606 if (has_failed) {
2607 PyErr_SetString(Tkinter_TclError,
2608 "Calling Tk_Init again after a previous call failed might deadlock");
2609 return NULL;
2610 }
2611
David Aschere2b4b322004-02-18 05:59:53 +00002612 /* We want to guard against calling Tk_Init() multiple times */
2613 CHECK_TCL_APPARTMENT;
2614 ENTER_TCL
2615 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2616 ENTER_OVERLAP
2617 if (err == TCL_ERROR) {
Thomas Wouters477c8d52006-05-27 19:21:47 +00002618 /* This sets an exception, but we cannot return right
2619 away because we need to exit the overlap first. */
2620 Tkinter_Error(self);
David Aschere2b4b322004-02-18 05:59:53 +00002621 } else {
2622 _tk_exists = Tkapp_Result(self);
2623 }
2624 LEAVE_OVERLAP_TCL
2625 if (err == TCL_ERROR) {
2626 return NULL;
2627 }
2628 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2629 if (Tk_Init(interp) == TCL_ERROR) {
2630 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Thomas Wouters477c8d52006-05-27 19:21:47 +00002631 has_failed = 1;
David Aschere2b4b322004-02-18 05:59:53 +00002632 return NULL;
2633 }
2634 }
2635 Py_INCREF(Py_None);
2636 return Py_None;
2637}
Barry Warsawfa701a81997-01-16 00:15:11 +00002638
Martin v. Löwisffad6332002-11-26 09:28:05 +00002639static PyObject *
2640Tkapp_WantObjects(PyObject *self, PyObject *args)
2641{
2642
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002643 int wantobjects = -1;
2644 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002645 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002646 if (wantobjects == -1)
2647 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002648 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002649
2650 Py_INCREF(Py_None);
2651 return Py_None;
2652}
2653
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002654static PyObject *
2655Tkapp_WillDispatch(PyObject *self, PyObject *args)
2656{
2657
2658 ((TkappObject*)self)->dispatching = 1;
2659
2660 Py_INCREF(Py_None);
2661 return Py_None;
2662}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002663
Barry Warsawfa701a81997-01-16 00:15:11 +00002664
Guido van Rossum18468821994-06-20 07:49:28 +00002665/**** Tkapp Method List ****/
2666
2667static PyMethodDef Tkapp_methods[] =
2668{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002669 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002670 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002671 {"call", Tkapp_Call, METH_OLDARGS},
2672 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2673 {"eval", Tkapp_Eval, METH_VARARGS},
2674 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2675 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2676 {"record", Tkapp_Record, METH_VARARGS},
2677 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2678 {"setvar", Tkapp_SetVar, METH_VARARGS},
2679 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2680 {"getvar", Tkapp_GetVar, METH_VARARGS},
2681 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2682 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2683 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2684 {"getint", Tkapp_GetInt, METH_VARARGS},
2685 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2686 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2687 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2688 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2689 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2690 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2691 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2692 {"split", Tkapp_Split, METH_VARARGS},
2693 {"merge", Tkapp_Merge, METH_OLDARGS},
2694 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2695 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002696#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002697 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2698 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002699#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002700 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2701 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2702 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2703 {"quit", Tkapp_Quit, METH_VARARGS},
2704 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Neal Norwitz44dbae82004-02-19 02:44:22 +00002705 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002706 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002707};
2708
Barry Warsawfa701a81997-01-16 00:15:11 +00002709
2710
Guido van Rossum18468821994-06-20 07:49:28 +00002711/**** Tkapp Type Methods ****/
2712
2713static void
Fred Drake509d79a2000-07-08 04:04:38 +00002714Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002715{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002716 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002717 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002718 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002719 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002720 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002721 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002722}
2723
2724static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002725Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002726{
Guido van Rossum35d43371997-08-02 00:09:09 +00002727 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002728}
2729
2730static PyTypeObject Tkapp_Type =
2731{
Guido van Rossum35d43371997-08-02 00:09:09 +00002732 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002733 0, /*ob_size */
2734 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002735 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002736 0, /*tp_itemsize */
2737 Tkapp_Dealloc, /*tp_dealloc */
2738 0, /*tp_print */
2739 Tkapp_GetAttr, /*tp_getattr */
2740 0, /*tp_setattr */
2741 0, /*tp_compare */
2742 0, /*tp_repr */
2743 0, /*tp_as_number */
2744 0, /*tp_as_sequence */
2745 0, /*tp_as_mapping */
2746 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002747};
2748
Barry Warsawfa701a81997-01-16 00:15:11 +00002749
2750
Guido van Rossum18468821994-06-20 07:49:28 +00002751/**** Tkinter Module ****/
2752
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002753typedef struct {
2754 PyObject* tuple;
2755 int size; /* current size */
2756 int maxsize; /* allocated size */
2757} FlattenContext;
2758
2759static int
2760_bump(FlattenContext* context, int size)
2761{
Guido van Rossum2834b972000-10-06 16:58:26 +00002762 /* expand tuple to hold (at least) size new items.
2763 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002764
2765 int maxsize = context->maxsize * 2;
2766
2767 if (maxsize < context->size + size)
2768 maxsize = context->size + size;
2769
2770 context->maxsize = maxsize;
2771
Tim Peters4324aa32001-05-28 22:30:08 +00002772 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002773}
2774
2775static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002776_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002777{
2778 /* add tuple or list to argument tuple (recursively) */
2779
2780 int i, size;
2781
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002782 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002783 PyErr_SetString(PyExc_ValueError,
2784 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002785 return 0;
2786 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002787 size = PyList_GET_SIZE(item);
2788 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002789 if (context->size + size > context->maxsize &&
2790 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002791 return 0;
2792 /* copy items to output tuple */
2793 for (i = 0; i < size; i++) {
2794 PyObject *o = PyList_GET_ITEM(item, i);
2795 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002796 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002797 return 0;
2798 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002799 if (context->size + 1 > context->maxsize &&
2800 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002801 return 0;
2802 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002803 PyTuple_SET_ITEM(context->tuple,
2804 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002805 }
2806 }
2807 } else if (PyTuple_Check(item)) {
2808 /* same, for tuples */
2809 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002810 if (context->size + size > context->maxsize &&
2811 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002812 return 0;
2813 for (i = 0; i < size; i++) {
2814 PyObject *o = PyTuple_GET_ITEM(item, i);
2815 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002816 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002817 return 0;
2818 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002819 if (context->size + 1 > context->maxsize &&
2820 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002821 return 0;
2822 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002823 PyTuple_SET_ITEM(context->tuple,
2824 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002825 }
2826 }
2827 } else {
2828 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2829 return 0;
2830 }
2831 return 1;
2832}
2833
2834static PyObject *
2835Tkinter_Flatten(PyObject* self, PyObject* args)
2836{
2837 FlattenContext context;
2838 PyObject* item;
2839
2840 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2841 return NULL;
2842
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002843 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002844 if (context.maxsize <= 0)
2845 return PyTuple_New(0);
2846
2847 context.tuple = PyTuple_New(context.maxsize);
2848 if (!context.tuple)
2849 return NULL;
2850
2851 context.size = 0;
2852
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002853 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002854 return NULL;
2855
Tim Peters4324aa32001-05-28 22:30:08 +00002856 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002857 return NULL;
2858
2859 return context.tuple;
2860}
2861
Guido van Rossum18468821994-06-20 07:49:28 +00002862static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002863Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002864{
Barry Warsawfa701a81997-01-16 00:15:11 +00002865 char *screenName = NULL;
2866 char *baseName = NULL;
2867 char *className = NULL;
2868 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002869 int wantobjects = 0;
David Aschere2b4b322004-02-18 05:59:53 +00002870 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002871 int sync = 0; /* pass -sync to wish */
2872 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002873
Guido van Rossum35d43371997-08-02 00:09:09 +00002874 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002875 if (baseName != NULL)
2876 baseName++;
2877 else
2878 baseName = Py_GetProgramName();
2879 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002880
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002881 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002882 &screenName, &baseName, &className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002883 &interactive, &wantobjects, &wantTk,
2884 &sync, &use))
Barry Warsawfa701a81997-01-16 00:15:11 +00002885 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002886
Barry Warsawfa701a81997-01-16 00:15:11 +00002887 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002888 interactive, wantobjects, wantTk,
2889 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002890}
2891
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002892static PyObject *
2893Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2894{
2895 int new_val;
2896 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2897 return NULL;
2898 if (new_val < 0) {
2899 PyErr_SetString(PyExc_ValueError,
2900 "busywaitinterval must be >= 0");
2901 return NULL;
2902 }
2903 Tkinter_busywaitinterval = new_val;
2904 Py_INCREF(Py_None);
2905 return Py_None;
2906}
2907
2908static char setbusywaitinterval_doc[] =
2909"setbusywaitinterval(n) -> None\n\
2910\n\
2911Set the busy-wait interval in milliseconds between successive\n\
2912calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2913It should be set to a divisor of the maximum time between\n\
2914frames in an animation.";
2915
2916static PyObject *
2917Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2918{
2919 return PyInt_FromLong(Tkinter_busywaitinterval);
2920}
2921
2922static char getbusywaitinterval_doc[] =
2923"getbusywaitinterval() -> int\n\
2924\n\
2925Return the current busy-wait interval between successive\n\
2926calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2927
Guido van Rossum18468821994-06-20 07:49:28 +00002928static PyMethodDef moduleMethods[] =
2929{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002930 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2931 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002932#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002933 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2934 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002935#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002936 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2937 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2938 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2939 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002940 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2941 setbusywaitinterval_doc},
2942 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2943 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002944 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002945};
2946
Guido van Rossum7bf15641998-05-22 18:28:17 +00002947#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002948
2949static int stdin_ready = 0;
2950
Guido van Rossumad4db171998-06-13 13:56:28 +00002951#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002952static void
Fred Drake509d79a2000-07-08 04:04:38 +00002953MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002954{
2955 stdin_ready = 1;
2956}
Guido van Rossumad4db171998-06-13 13:56:28 +00002957#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002958
Martin v. Löwisa9656492003-03-30 08:44:58 +00002959#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002960static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002961#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002962
Guido van Rossum18468821994-06-20 07:49:28 +00002963static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002964EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002965{
Guido van Rossumad4db171998-06-13 13:56:28 +00002966#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002967 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002968#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002969#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002970 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002971#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002972 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002973 errorInCmd = 0;
2974#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002975 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002976 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002977#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002978 while (!errorInCmd && !stdin_ready) {
2979 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002980#ifdef MS_WINDOWS
2981 if (_kbhit()) {
2982 stdin_ready = 1;
2983 break;
2984 }
2985#endif
2986#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002987 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002988 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002989 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002990
Guido van Rossum00d93061998-05-28 23:06:38 +00002991 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002992
2993 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002994 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002995 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002996 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002997 Py_END_ALLOW_THREADS
2998#else
2999 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003000#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003001
3002 if (result < 0)
3003 break;
3004 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003005#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00003006 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003007#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003008 if (errorInCmd) {
3009 errorInCmd = 0;
3010 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3011 excInCmd = valInCmd = trbInCmd = NULL;
3012 PyErr_Print();
3013 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003014#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00003015 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003016#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003017 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003018}
Guido van Rossum18468821994-06-20 07:49:28 +00003019
Guido van Rossum00d93061998-05-28 23:06:38 +00003020#endif
3021
Guido van Rossum7bf15641998-05-22 18:28:17 +00003022static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003023EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003024{
Guido van Rossum00d93061998-05-28 23:06:38 +00003025#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003026 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003027#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003028 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003029#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003030 PyOS_InputHook = EventHook;
3031 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003032#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003033}
3034
3035static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003036DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003037{
Guido van Rossum00d93061998-05-28 23:06:38 +00003038#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003039 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3040 PyOS_InputHook = NULL;
3041 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003042#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003043}
3044
Barry Warsawfa701a81997-01-16 00:15:11 +00003045
3046/* all errors will be checked in one fell swoop in init_tkinter() */
3047static void
Fred Drake509d79a2000-07-08 04:04:38 +00003048ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003049{
3050 PyObject *v = PyInt_FromLong(val);
3051 if (v) {
3052 PyDict_SetItemString(d, name, v);
3053 Py_DECREF(v);
3054 }
3055}
3056static void
Fred Drake509d79a2000-07-08 04:04:38 +00003057ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003058{
3059 PyObject *v = PyString_FromString(val);
3060 if (v) {
3061 PyDict_SetItemString(d, name, v);
3062 Py_DECREF(v);
3063 }
3064}
3065
3066
Mark Hammond62b1ab12002-07-23 06:31:15 +00003067PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003068init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003069{
Barry Warsawfa701a81997-01-16 00:15:11 +00003070 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003071
Barry Warsawfa701a81997-01-16 00:15:11 +00003072 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003073
3074#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003075 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003076#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003077
Barry Warsawfa701a81997-01-16 00:15:11 +00003078 m = Py_InitModule("_tkinter", moduleMethods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00003079 if (m == NULL)
3080 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003081
Barry Warsawfa701a81997-01-16 00:15:11 +00003082 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003083 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003084 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003085
Guido van Rossum35d43371997-08-02 00:09:09 +00003086 ins_long(d, "READABLE", TCL_READABLE);
3087 ins_long(d, "WRITABLE", TCL_WRITABLE);
3088 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3089 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3090 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3091 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3092 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3093 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3094 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003095 ins_string(d, "TK_VERSION", TK_VERSION);
3096 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003097
Guido van Rossum83551bf1997-09-13 00:44:23 +00003098 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003099
3100 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003101 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3102
Martin v. Löwisffad6332002-11-26 09:28:05 +00003103 PyTclObject_Type.ob_type = &PyType_Type;
3104 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003105
3106#ifdef TK_AQUA
3107 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3108 * start waking up. Note that Tcl_FindExecutable will do this, this
3109 * code must be above it! The original warning from
3110 * tkMacOSXAppInit.c is copied below.
3111 *
3112 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3113 * Tcl interpreter for now. It probably should work to do this
3114 * in the other order, but for now it doesn't seem to.
3115 *
3116 */
3117 Tk_MacOSXSetupTkNotifier();
3118#endif
3119
3120
Guido van Rossume187b0e2000-03-27 21:46:29 +00003121 /* This helps the dynamic loader; in Unicode aware Tcl versions
3122 it also helps Tcl find its encodings. */
3123 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003124
Barry Warsawfa701a81997-01-16 00:15:11 +00003125 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003126 return;
3127
Guido van Rossum43ff8681998-07-14 18:02:13 +00003128#if 0
3129 /* This was not a good idea; through <Destroy> bindings,
3130 Tcl_Finalize() may invoke Python code but at that point the
3131 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003132 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003133#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003134
Guido van Rossum18468821994-06-20 07:49:28 +00003135}