blob: 74fe0f8d7838e7fe03483d72d5531b64cc1a9e4c [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
101/* Tcl_CreateFileHandler() changed several times; these macros deal with the
102 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
103 Unix, only because Jack added it back); when available on Windows, it only
104 applies to sockets. */
105
Guido van Rossum7bf15641998-05-22 18:28:17 +0000106#ifdef MS_WINDOWS
107#define FHANDLETYPE TCL_WIN_SOCKET
108#else
109#define FHANDLETYPE TCL_UNIX_FD
110#endif
111
Guido van Rossum00d93061998-05-28 23:06:38 +0000112/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
113 which uses this to handle Tcl events while the user is typing commands. */
114
115#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000116#define WAIT_FOR_STDIN
117#endif
118
Guido van Rossum00d93061998-05-28 23:06:38 +0000119#endif /* HAVE_CREATEFILEHANDLER */
120
Guido van Rossumad4db171998-06-13 13:56:28 +0000121#ifdef MS_WINDOWS
122#include <conio.h>
123#define WAIT_FOR_STDIN
124#endif
125
Guido van Rossum00d93061998-05-28 23:06:38 +0000126#ifdef WITH_THREAD
127
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000128/* The threading situation is complicated. Tcl is not thread-safe, except
129 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000130 So we need to use a lock around all uses of Tcl. Previously, the Python
131 interpreter lock was used for this. However, this causes problems when
132 other Python threads need to run while Tcl is blocked waiting for events.
133
134 To solve this problem, a separate lock for Tcl is introduced. Holding it
135 is incompatible with holding Python's interpreter lock. The following four
136 macros manipulate both locks together.
137
138 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
139 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
140 that could call an event handler, or otherwise affect the state of a Tcl
141 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000142 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000143 released and the lock for Tcl has been acquired.
144
Guido van Rossum5e977831998-06-15 14:03:52 +0000145 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
146 (For example, when transferring data from the Tcl interpreter result to a
147 Python string object.) This can be done by using different macros to close
148 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
149 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
150 releases the Tcl lock.
151
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000152 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000153 handlers when the handler needs to use Python. Such event handlers are
154 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000155 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000156 the Python interpreter lock, restoring the appropriate thread state, and
157 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
158 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000159 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000160
161 These locks expand to several statements and brackets; they should not be
162 used in branches of if statements and the like.
163
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000164 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
165 only valid in the thread that created it, and all Tk activity must happen in this
166 thread, also. That means that the mainloop must be invoked in the thread that
167 created the interpreter. Invoking commands from other threads is possible;
168 _tkinter will queue an event for the interpreter thread, which will then
169 execute the command and pass back the result. If the main thread is not in the
170 mainloop, and invoking commands causes an exception; if the main loop is running
171 but not processing events, the command invocation will block.
172
173 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
174 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
175 threads. So we use the Tcl TLS API.
176
Guido van Rossum00d93061998-05-28 23:06:38 +0000177*/
178
Guido van Rossum65d5b571998-12-21 19:32:43 +0000179static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000180
181#ifdef TCL_THREADS
182static Tcl_ThreadDataKey state_key;
183typedef PyThreadState *ThreadSpecificData;
184#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
185#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000186static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000187#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000188
189#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000190 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000191 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000192
193#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000194 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000195
Guido van Rossum62320c91998-06-15 04:36:09 +0000196#define ENTER_OVERLAP \
197 Py_END_ALLOW_THREADS
198
199#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000200 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000201
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000202#define ENTER_PYTHON \
203 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000204 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000205
206#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000207 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000208 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
209
210#define CHECK_TCL_APPARTMENT \
211 if (((TkappObject *)self)->threaded && \
212 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
213 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
214 return 0; \
215 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000216
217#else
218
219#define ENTER_TCL
220#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000221#define ENTER_OVERLAP
222#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000223#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000224#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000225#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000226
227#endif
228
Guido van Rossum97867b21996-08-08 19:09:53 +0000229#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000230#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000231#endif
232
Guido van Rossum18468821994-06-20 07:49:28 +0000233/**** Tkapp Object Declaration ****/
234
Jeremy Hylton938ace62002-07-17 16:30:39 +0000235static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000236
Guido van Rossum00d93061998-05-28 23:06:38 +0000237typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000238 PyObject_HEAD
239 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000240 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000241 int threaded; /* True if tcl_platform[threaded] */
242 Tcl_ThreadId thread_id;
243 int dispatching;
244 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000245 So we cache interesting types here. */
246 Tcl_ObjType *BooleanType;
247 Tcl_ObjType *ByteArrayType;
248 Tcl_ObjType *DoubleType;
249 Tcl_ObjType *IntType;
250 Tcl_ObjType *ListType;
251 Tcl_ObjType *ProcBodyType;
252 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000253} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000254
255#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000256#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000257#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000258
Guido van Rossum35d43371997-08-02 00:09:09 +0000259#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000260(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000261
Barry Warsawfa701a81997-01-16 00:15:11 +0000262
263
Guido van Rossum18468821994-06-20 07:49:28 +0000264/**** Error Handling ****/
265
266static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000267static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000268static int errorInCmd = 0;
269static PyObject *excInCmd;
270static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000271static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000272
Barry Warsawfa701a81997-01-16 00:15:11 +0000273
274
Guido van Rossum18468821994-06-20 07:49:28 +0000275static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000276Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000277{
Barry Warsawfa701a81997-01-16 00:15:11 +0000278 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
279 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000280}
281
Barry Warsawfa701a81997-01-16 00:15:11 +0000282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
Guido van Rossum18468821994-06-20 07:49:28 +0000284/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000285
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000286static int Tkinter_busywaitinterval = 20;
287
Guido van Rossum00d93061998-05-28 23:06:38 +0000288#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000289#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000290
Guido van Rossum00d93061998-05-28 23:06:38 +0000291/* Millisecond sleep() for Unix platforms. */
292
293static void
Fred Drake509d79a2000-07-08 04:04:38 +0000294Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000295{
296 /* XXX Too bad if you don't have select(). */
297 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000298 t.tv_sec = milli/1000;
299 t.tv_usec = (milli%1000) * 1000;
300 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
301}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000302#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000303
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000304/* Wait up to 1s for the mainloop to come up. */
305
306static int
307WaitForMainloop(TkappObject* self)
308{
309 int i;
310 for (i = 0; i < 10; i++) {
311 if (self->dispatching)
312 return 1;
313 Py_BEGIN_ALLOW_THREADS
314 Sleep(100);
315 Py_END_ALLOW_THREADS
316 }
317 if (self->dispatching)
318 return 1;
319 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
320 return 0;
321}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000322#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000323
Guido van Rossum00d93061998-05-28 23:06:38 +0000324
Guido van Rossum18468821994-06-20 07:49:28 +0000325static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000326AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000327{
Guido van Rossum35d43371997-08-02 00:09:09 +0000328 if (PyString_Check(value))
329 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000330#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000331 else if (PyUnicode_Check(value)) {
332 PyObject *v = PyUnicode_AsUTF8String(value);
333 if (v == NULL)
334 return NULL;
335 if (PyList_Append(tmp, v) != 0) {
336 Py_DECREF(v);
337 return NULL;
338 }
339 Py_DECREF(v);
340 return PyString_AsString(v);
341 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000342#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000343 else {
344 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000345 if (v == NULL)
346 return NULL;
347 if (PyList_Append(tmp, v) != 0) {
348 Py_DECREF(v);
349 return NULL;
350 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000351 Py_DECREF(v);
352 return PyString_AsString(v);
353 }
Guido van Rossum18468821994-06-20 07:49:28 +0000354}
355
Barry Warsawfa701a81997-01-16 00:15:11 +0000356
357
Guido van Rossum18468821994-06-20 07:49:28 +0000358#define ARGSZ 64
359
360static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000361Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000362{
Barry Warsawfa701a81997-01-16 00:15:11 +0000363 PyObject *tmp = NULL;
364 char *argvStore[ARGSZ];
365 char **argv = NULL;
366 int fvStore[ARGSZ];
367 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000368 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000369 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000370
Barry Warsawfa701a81997-01-16 00:15:11 +0000371 if (!(tmp = PyList_New(0)))
372 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000373
Barry Warsawfa701a81997-01-16 00:15:11 +0000374 argv = argvStore;
375 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000376
Barry Warsawfa701a81997-01-16 00:15:11 +0000377 if (args == NULL)
378 argc = 0;
379
380 else if (!PyTuple_Check(args)) {
381 argc = 1;
382 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000383 if (!(argv[0] = AsString(args, tmp)))
384 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000385 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000386 else {
387 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000388
Barry Warsawfa701a81997-01-16 00:15:11 +0000389 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000390 argv = (char **)ckalloc(argc * sizeof(char *));
391 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000392 if (argv == NULL || fv == NULL) {
393 PyErr_NoMemory();
394 goto finally;
395 }
396 }
397
398 for (i = 0; i < argc; i++) {
399 PyObject *v = PyTuple_GetItem(args, i);
400 if (PyTuple_Check(v)) {
401 fv[i] = 1;
402 if (!(argv[i] = Merge(v)))
403 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000404 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000405 }
406 else if (v == Py_None) {
407 argc = i;
408 break;
409 }
410 else {
411 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000412 if (!(argv[i] = AsString(v, tmp)))
413 goto finally;
414 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000415 }
416 }
Guido van Rossum18468821994-06-20 07:49:28 +0000417 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000418 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000419 if (res == NULL)
420 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000421
Barry Warsawfa701a81997-01-16 00:15:11 +0000422 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000423 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000424 if (fv[i]) {
425 ckfree(argv[i]);
426 }
427 if (argv != argvStore)
428 ckfree(FREECAST argv);
429 if (fv != fvStore)
430 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000431
Barry Warsawfa701a81997-01-16 00:15:11 +0000432 Py_DECREF(tmp);
433 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000434}
435
Barry Warsawfa701a81997-01-16 00:15:11 +0000436
437
Guido van Rossum18468821994-06-20 07:49:28 +0000438static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000439Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000440{
Barry Warsawfa701a81997-01-16 00:15:11 +0000441 int argc;
442 char **argv;
443 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000444
Barry Warsawfa701a81997-01-16 00:15:11 +0000445 if (list == NULL) {
446 Py_INCREF(Py_None);
447 return Py_None;
448 }
Guido van Rossum18468821994-06-20 07:49:28 +0000449
Guido van Rossum00d93061998-05-28 23:06:38 +0000450 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000451 /* Not a list.
452 * Could be a quoted string containing funnies, e.g. {"}.
453 * Return the string itself.
454 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000455 return PyString_FromString(list);
456 }
Guido van Rossum18468821994-06-20 07:49:28 +0000457
Barry Warsawfa701a81997-01-16 00:15:11 +0000458 if (argc == 0)
459 v = PyString_FromString("");
460 else if (argc == 1)
461 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000462 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000463 int i;
464 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000465
Barry Warsawfa701a81997-01-16 00:15:11 +0000466 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000467 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000468 Py_DECREF(v);
469 v = NULL;
470 break;
471 }
472 PyTuple_SetItem(v, i, w);
473 }
474 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000475 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000476 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000477}
478
Martin v. Löwisffad6332002-11-26 09:28:05 +0000479/* In some cases, Tcl will still return strings that are supposed to be
480 lists. SplitObj walks through a nested tuple, finding string objects that
481 need to be split. */
482
483PyObject *
484SplitObj(PyObject *arg)
485{
486 if (PyTuple_Check(arg)) {
487 int i, size;
488 PyObject *elem, *newelem, *result;
489
490 size = PyTuple_Size(arg);
491 result = NULL;
492 /* Recursively invoke SplitObj for all tuple items.
493 If this does not return a new object, no action is
494 needed. */
495 for(i = 0; i < size; i++) {
496 elem = PyTuple_GetItem(arg, i);
497 newelem = SplitObj(elem);
498 if (!newelem) {
499 Py_XDECREF(result);
500 return NULL;
501 }
502 if (!result) {
503 int k;
504 if (newelem == elem) {
505 Py_DECREF(newelem);
506 continue;
507 }
508 result = PyTuple_New(size);
509 if (!result)
510 return NULL;
511 for(k = 0; k < i; k++) {
512 elem = PyTuple_GetItem(arg, k);
513 Py_INCREF(elem);
514 PyTuple_SetItem(result, k, elem);
515 }
516 }
517 PyTuple_SetItem(result, i, newelem);
518 }
519 if (result)
520 return result;
521 /* Fall through, returning arg. */
522 }
523 else if (PyString_Check(arg)) {
524 int argc;
525 char **argv;
526 char *list = PyString_AsString(arg);
527
528 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
529 Py_INCREF(arg);
530 return arg;
531 }
532 Tcl_Free(FREECAST argv);
533 if (argc > 1)
534 return Split(PyString_AsString(arg));
535 /* Fall through, returning arg. */
536 }
537 Py_INCREF(arg);
538 return arg;
539}
Barry Warsawfa701a81997-01-16 00:15:11 +0000540
541
Guido van Rossum18468821994-06-20 07:49:28 +0000542/**** Tkapp Object ****/
543
544#ifndef WITH_APPINIT
545int
Fred Drake509d79a2000-07-08 04:04:38 +0000546Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000547{
Barry Warsawfa701a81997-01-16 00:15:11 +0000548 Tk_Window main;
David Aschere2b4b322004-02-18 05:59:53 +0000549 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000550
Barry Warsawfa701a81997-01-16 00:15:11 +0000551 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000552 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000553 return TCL_ERROR;
554 }
David Aschere2b4b322004-02-18 05:59:53 +0000555 _tkinter_skip_tk_init = Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
556 if (_tkinter_skip_tk_init == NULL || strcmp(_tkinter_skip_tk_init, "1") != 0) {
557 main = Tk_MainWindow(interp);
558 if (Tk_Init(interp) == TCL_ERROR) {
559 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
560 return TCL_ERROR;
561 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000562 }
563 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000564}
565#endif /* !WITH_APPINIT */
566
Guido van Rossum18468821994-06-20 07:49:28 +0000567
Barry Warsawfa701a81997-01-16 00:15:11 +0000568
569
570/* Initialize the Tk application; see the `main' function in
571 * `tkMain.c'.
572 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000573
Thomas Wouters58d05102000-07-24 14:43:35 +0000574static void EnableEventHook(void); /* Forward */
575static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000576
Barry Warsawfa701a81997-01-16 00:15:11 +0000577static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000578Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000579 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000580{
581 TkappObject *v;
582 char *argv0;
Guido van Rossumb18618d2000-05-03 23:44:39 +0000583 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000584 if (v == NULL)
585 return NULL;
586
587 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000588 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000589 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
590 TCL_GLOBAL_ONLY) != NULL;
591 v->thread_id = Tcl_GetCurrentThread();
592 v->dispatching = 0;
593
594#ifndef TCL_THREADS
595 if (v->threaded) {
596 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
597 Py_DECREF(v);
598 return 0;
599 }
600#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000601#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000602 if (v->threaded && tcl_lock) {
603 /* If Tcl is threaded, we don't need the lock. */
604 PyThread_free_lock(tcl_lock);
605 tcl_lock = NULL;
606 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000607#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000608
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000609 v->BooleanType = Tcl_GetObjType("boolean");
610 v->ByteArrayType = Tcl_GetObjType("bytearray");
611 v->DoubleType = Tcl_GetObjType("double");
612 v->IntType = Tcl_GetObjType("int");
613 v->ListType = Tcl_GetObjType("list");
614 v->ProcBodyType = Tcl_GetObjType("procbody");
615 v->StringType = Tcl_GetObjType("string");
616
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000617 /* Delete the 'exit' command, which can screw things up */
618 Tcl_DeleteCommand(v->interp, "exit");
619
Barry Warsawfa701a81997-01-16 00:15:11 +0000620 if (screenName != NULL)
621 Tcl_SetVar2(v->interp, "env", "DISPLAY",
622 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000623
Barry Warsawfa701a81997-01-16 00:15:11 +0000624 if (interactive)
625 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
626 else
627 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000628
Barry Warsawfa701a81997-01-16 00:15:11 +0000629 /* This is used to get the application class for Tk 4.1 and up */
630 argv0 = (char*)ckalloc(strlen(className) + 1);
631 if (!argv0) {
632 PyErr_NoMemory();
633 Py_DECREF(v);
634 return NULL;
635 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000636
Barry Warsawfa701a81997-01-16 00:15:11 +0000637 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000638 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000639 argv0[0] = tolower(argv0[0]);
640 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
641 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000642
David Aschere2b4b322004-02-18 05:59:53 +0000643 if (! wantTk) {
644 Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
645 }
646
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000647 /* some initial arguments need to be in argv */
648 if (sync || use) {
649 int len = 0;
650 if (sync)
651 len += sizeof "-sync";
652 if (use)
653 len += strlen(use) + sizeof "-use ";
654
655 char *args = (char*)ckalloc(len);
656 if (!args) {
657 PyErr_NoMemory();
658 Py_DECREF(v);
659 return NULL;
660 }
661
662 args[0] = '\0';
663 if (sync)
664 strcat(args, "-sync");
665 if (use) {
666 if (sync)
667 strcat(args, " ");
668 strcat(args, "-use ");
669 strcat(args, use);
670 }
671
672 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
673 ckfree(args);
674 }
675
Barry Warsawfa701a81997-01-16 00:15:11 +0000676 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000677 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000678
Guido van Rossum7bf15641998-05-22 18:28:17 +0000679 EnableEventHook();
680
Barry Warsawfa701a81997-01-16 00:15:11 +0000681 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000682}
683
Barry Warsawfa701a81997-01-16 00:15:11 +0000684
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000685static void
686Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
687 Tcl_Condition *cond, Tcl_Mutex *mutex)
688{
689 Py_BEGIN_ALLOW_THREADS;
690 Tcl_MutexLock(mutex);
691 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
692 Tcl_ThreadAlert(self->thread_id);
693 Tcl_ConditionWait(cond, mutex, NULL);
694 Tcl_MutexUnlock(mutex);
695 Py_END_ALLOW_THREADS
696}
697
Barry Warsawfa701a81997-01-16 00:15:11 +0000698
Guido van Rossum18468821994-06-20 07:49:28 +0000699/** Tcl Eval **/
700
Martin v. Löwisffad6332002-11-26 09:28:05 +0000701typedef struct {
702 PyObject_HEAD
703 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000704 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000705} PyTclObject;
706
707staticforward PyTypeObject PyTclObject_Type;
708#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
709
710static PyObject *
711newPyTclObject(Tcl_Obj *arg)
712{
713 PyTclObject *self;
714 self = PyObject_New(PyTclObject, &PyTclObject_Type);
715 if (self == NULL)
716 return NULL;
717 Tcl_IncrRefCount(arg);
718 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000719 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000720 return (PyObject*)self;
721}
722
723static void
724PyTclObject_dealloc(PyTclObject *self)
725{
726 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000727 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000728 PyObject_Del(self);
729}
730
731static PyObject *
732PyTclObject_str(PyTclObject *self)
733{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000734 if (self->string && PyString_Check(self->string)) {
735 Py_INCREF(self->string);
736 return self->string;
737 }
738 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000739 return PyString_FromString(Tcl_GetString(self->value));
740}
741
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000742static char*
743PyTclObject_TclString(PyObject *self)
744{
745 return Tcl_GetString(((PyTclObject*)self)->value);
746}
747
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000748/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000749PyDoc_STRVAR(PyTclObject_string__doc__,
750"the string representation of this object, either as string or Unicode");
751
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000752static PyObject *
753PyTclObject_string(PyTclObject *self, void *ignored)
754{
755 char *s;
756 int i, len;
757 if (!self->string) {
758 s = Tcl_GetStringFromObj(self->value, &len);
759 for (i = 0; i < len; i++)
760 if (s[i] & 0x80)
761 break;
762#ifdef Py_USING_UNICODE
763 if (i == len)
764 /* It is an ASCII string. */
765 self->string = PyString_FromStringAndSize(s, len);
766 else {
767 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
768 if (!self->string) {
769 PyErr_Clear();
770 self->string = PyString_FromStringAndSize(s, len);
771 }
772 }
773#else
774 self->string = PyString_FromStringAndSize(s, len);
775#endif
776 if (!self->string)
777 return NULL;
778 }
779 Py_INCREF(self->string);
780 return self->string;
781}
782
783#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000784PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
785
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000786static PyObject *
787PyTclObject_unicode(PyTclObject *self, void *ignored)
788{
789 char *s;
790 int len;
791 if (self->string && PyUnicode_Check(self->string)) {
792 Py_INCREF(self->string);
793 return self->string;
794 }
795 /* XXX Could chache result if it is non-ASCII. */
796 s = Tcl_GetStringFromObj(self->value, &len);
797 return PyUnicode_DecodeUTF8(s, len, "strict");
798}
799#endif
800
Martin v. Löwisffad6332002-11-26 09:28:05 +0000801static PyObject *
802PyTclObject_repr(PyTclObject *self)
803{
804 char buf[50];
805 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
806 self->value->typePtr->name, (int)self->value);
807 return PyString_FromString(buf);
808}
809
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000810static int
811PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
812{
813 int res;
814 res = strcmp(Tcl_GetString(self->value),
815 Tcl_GetString(other->value));
816 if (res < 0) return -1;
817 if (res > 0) return 1;
818 return 0;
819}
820
Martin v. Löwis39195712003-01-04 00:33:13 +0000821PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
822
Martin v. Löwisffad6332002-11-26 09:28:05 +0000823static PyObject*
824get_typename(PyTclObject* obj, void* ignored)
825{
826 return PyString_FromString(obj->value->typePtr->name);
827}
828
Martin v. Löwis39195712003-01-04 00:33:13 +0000829
Martin v. Löwisffad6332002-11-26 09:28:05 +0000830static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000831 {"typename", (getter)get_typename, NULL, get_typename__doc__},
832 {"string", (getter)PyTclObject_string, NULL,
833 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000834 {0},
835};
836
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000837static PyMethodDef PyTclObject_methods[] = {
838 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000839 PyTclObject_unicode__doc__},
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000840 {0}
841};
842
Martin v. Löwisffad6332002-11-26 09:28:05 +0000843statichere PyTypeObject PyTclObject_Type = {
844 PyObject_HEAD_INIT(NULL)
845 0, /*ob_size*/
846 "_tkinter.Tcl_Obj", /*tp_name*/
847 sizeof(PyTclObject), /*tp_basicsize*/
848 0, /*tp_itemsize*/
849 /* methods */
850 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
851 0, /*tp_print*/
852 0, /*tp_getattr*/
853 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000854 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000855 (reprfunc)PyTclObject_repr, /*tp_repr*/
856 0, /*tp_as_number*/
857 0, /*tp_as_sequence*/
858 0, /*tp_as_mapping*/
859 0, /*tp_hash*/
860 0, /*tp_call*/
861 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000862 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000863 0, /*tp_setattro*/
864 0, /*tp_as_buffer*/
865 Py_TPFLAGS_DEFAULT, /*tp_flags*/
866 0, /*tp_doc*/
867 0, /*tp_traverse*/
868 0, /*tp_clear*/
869 0, /*tp_richcompare*/
870 0, /*tp_weaklistoffset*/
871 0, /*tp_iter*/
872 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000873 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000874 0, /*tp_members*/
875 PyTclObject_getsetlist, /*tp_getset*/
876 0, /*tp_base*/
877 0, /*tp_dict*/
878 0, /*tp_descr_get*/
879 0, /*tp_descr_set*/
880 0, /*tp_dictoffset*/
881 0, /*tp_init*/
882 0, /*tp_alloc*/
883 0, /*tp_new*/
884 0, /*tp_free*/
885 0, /*tp_is_gc*/
886};
887
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000888static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000889AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000890{
891 Tcl_Obj *result;
892
893 if (PyString_Check(value))
894 return Tcl_NewStringObj(PyString_AS_STRING(value),
895 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000896 else if (PyBool_Check(value))
897 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000898 else if (PyInt_Check(value))
899 return Tcl_NewLongObj(PyInt_AS_LONG(value));
900 else if (PyFloat_Check(value))
901 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
902 else if (PyTuple_Check(value)) {
903 Tcl_Obj **argv = (Tcl_Obj**)
904 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
905 int i;
906 if(!argv)
907 return 0;
908 for(i=0;i<PyTuple_Size(value);i++)
909 argv[i] = AsObj(PyTuple_GetItem(value,i));
910 result = Tcl_NewListObj(PyTuple_Size(value), argv);
911 ckfree(FREECAST argv);
912 return result;
913 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000914#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000915 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000916 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
917 int size = PyUnicode_GET_SIZE(value);
918 /* This #ifdef assumes that Tcl uses UCS-2.
919 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000920#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000921 Tcl_UniChar *outbuf;
922 int i;
923 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
924 if (!outbuf) {
925 PyErr_NoMemory();
926 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000927 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000928 for (i = 0; i < size; i++) {
929 if (inbuf[i] >= 0x10000) {
930 /* Tcl doesn't do UTF-16, yet. */
931 PyErr_SetString(PyExc_ValueError,
932 "unsupported character");
933 ckfree(FREECAST outbuf);
934 return NULL;
935 }
936 outbuf[i] = inbuf[i];
937 }
938 result = Tcl_NewUnicodeObj(outbuf, size);
939 ckfree(FREECAST outbuf);
940 return result;
941#else
942 return Tcl_NewUnicodeObj(inbuf, size);
943#endif
944
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000945 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000946#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000947 else if(PyTclObject_Check(value)) {
948 Tcl_Obj *v = ((PyTclObject*)value)->value;
949 Tcl_IncrRefCount(v);
950 return v;
951 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000952 else {
953 PyObject *v = PyObject_Str(value);
954 if (!v)
955 return 0;
956 result = AsObj(v);
957 Py_DECREF(v);
958 return result;
959 }
960}
961
Martin v. Löwisffad6332002-11-26 09:28:05 +0000962static PyObject*
963FromObj(PyObject* tkapp, Tcl_Obj *value)
964{
965 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000966 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000967
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000968 if (value->typePtr == NULL) {
969 /* If the result contains any bytes with the top bit set,
970 it's UTF-8 and we should decode it to Unicode */
971#ifdef Py_USING_UNICODE
972 int i;
973 char *s = value->bytes;
974 int len = value->length;
975 for (i = 0; i < len; i++) {
976 if (value->bytes[i] & 0x80)
977 break;
978 }
979
980 if (i == value->length)
981 result = PyString_FromStringAndSize(s, len);
982 else {
983 /* Convert UTF-8 to Unicode string */
984 result = PyUnicode_DecodeUTF8(s, len, "strict");
985 if (result == NULL) {
986 PyErr_Clear();
987 result = PyString_FromStringAndSize(s, len);
988 }
989 }
990#else
991 res = PyString_FromStringAndSize(value->bytes, value->length);
992#endif
993 return result;
994 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000995
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000996 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000997 result = value->internalRep.longValue ? Py_True : Py_False;
998 Py_INCREF(result);
999 return result;
1000 }
1001
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001002 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001003 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +00001004 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001005 return PyString_FromStringAndSize(data, size);
1006 }
1007
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001008 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001009 return PyFloat_FromDouble(value->internalRep.doubleValue);
1010 }
1011
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001012 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001013 return PyInt_FromLong(value->internalRep.longValue);
1014 }
1015
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001016 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001017 int size;
1018 int i, status;
1019 PyObject *elem;
1020 Tcl_Obj *tcl_elem;
1021
1022 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1023 if (status == TCL_ERROR)
1024 return Tkinter_Error(tkapp);
1025 result = PyTuple_New(size);
1026 if (!result)
1027 return NULL;
1028 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001029 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001030 value, i, &tcl_elem);
1031 if (status == TCL_ERROR) {
1032 Py_DECREF(result);
1033 return Tkinter_Error(tkapp);
1034 }
1035 elem = FromObj(tkapp, tcl_elem);
1036 if (!elem) {
1037 Py_DECREF(result);
1038 return NULL;
1039 }
1040 PyTuple_SetItem(result, i, elem);
1041 }
1042 return result;
1043 }
1044
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001045 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001046 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001047 }
1048
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001049 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001050#ifdef Py_USING_UNICODE
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
1070#else
1071 int size;
1072 char *c;
1073 c = Tcl_GetStringFromObj(value, &size);
1074 return PyString_FromStringAndSize(c, size);
1075#endif
1076 }
1077
1078 return newPyTclObject(value);
1079}
1080
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001081/* This mutex synchronizes inter-thread command calls. */
1082
1083TCL_DECLARE_MUTEX(call_mutex)
1084
1085typedef struct Tkapp_CallEvent {
1086 Tcl_Event ev; /* Must be first */
1087 TkappObject *self;
1088 PyObject *args;
1089 int flags;
1090 PyObject **res;
1091 PyObject **exc_type, **exc_value, **exc_tb;
1092 Tcl_Condition done;
1093} Tkapp_CallEvent;
1094
1095void
1096Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001097{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001098 int i;
1099 for (i = 0; i < objc; i++)
1100 Tcl_DecrRefCount(objv[i]);
1101 if (objv != objStore)
1102 ckfree(FREECAST objv);
1103}
Guido van Rossum18468821994-06-20 07:49:28 +00001104
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001105/* Convert Python objects to Tcl objects. This must happen in the
1106 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001107
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001108static Tcl_Obj**
1109Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1110{
1111 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001112 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001113 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001114 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001115
Guido van Rossum212643f1998-04-29 16:22:14 +00001116 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001117 objv[0] = AsObj(args);
1118 if (objv[0] == 0)
1119 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001120 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001121 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001122 }
1123 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001124 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001125
Guido van Rossum632de272000-03-29 00:19:50 +00001126 if (objc > ARGSZ) {
1127 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1128 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001129 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001130 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001131 goto finally;
1132 }
1133 }
1134
Guido van Rossum632de272000-03-29 00:19:50 +00001135 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001136 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001137 if (v == Py_None) {
1138 objc = i;
1139 break;
1140 }
Guido van Rossum632de272000-03-29 00:19:50 +00001141 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001142 if (!objv[i]) {
1143 /* Reset objc, so it attempts to clear
1144 objects only up to i. */
1145 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001146 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001147 }
Guido van Rossum632de272000-03-29 00:19:50 +00001148 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001149 }
1150 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001151 *pobjc = objc;
1152 return objv;
1153finally:
1154 Tkapp_CallDeallocArgs(objv, objStore, objc);
1155 return NULL;
1156}
Guido van Rossum212643f1998-04-29 16:22:14 +00001157
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001158/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001159
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001160static PyObject*
1161Tkapp_CallResult(TkappObject *self)
1162{
1163 PyObject *res = NULL;
1164 if(self->wantobjects) {
1165 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001166 /* Not sure whether the IncrRef is necessary, but something
1167 may overwrite the interpreter result while we are
1168 converting it. */
1169 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001170 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001171 Tcl_DecrRefCount(value);
1172 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001173 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001174 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001175
Guido van Rossum990f5c62000-05-04 15:07:16 +00001176 /* If the result contains any bytes with the top bit set,
1177 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001178#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001179 while (*p != '\0') {
1180 if (*p & 0x80)
1181 break;
1182 p++;
1183 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001184
Guido van Rossum990f5c62000-05-04 15:07:16 +00001185 if (*p == '\0')
1186 res = PyString_FromStringAndSize(s, (int)(p-s));
1187 else {
1188 /* Convert UTF-8 to Unicode string */
1189 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001190 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1191 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001192 PyErr_Clear();
1193 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001194 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001195 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001196#else
1197 p = strchr(p, '\0');
1198 res = PyString_FromStringAndSize(s, (int)(p-s));
1199#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001200 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001201 return res;
1202}
Guido van Rossum632de272000-03-29 00:19:50 +00001203
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001204/* Tkapp_CallProc is the event procedure that is executed in the context of
1205 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1206 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001207
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001208static int
1209Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1210{
1211 Tcl_Obj *objStore[ARGSZ];
1212 Tcl_Obj **objv;
1213 int objc;
1214 int i;
1215 ENTER_PYTHON
1216 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1217 if (!objv) {
1218 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1219 *(e->res) = NULL;
1220 }
1221 LEAVE_PYTHON
1222 if (!objv)
1223 goto done;
1224 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1225 ENTER_PYTHON
1226 if (i == TCL_ERROR) {
1227 *(e->res) = NULL;
1228 *(e->exc_type) = NULL;
1229 *(e->exc_tb) = NULL;
1230 *(e->exc_value) = PyObject_CallFunction(
1231 Tkinter_TclError, "s",
1232 Tcl_GetStringResult(e->self->interp));
1233 }
1234 else {
1235 *(e->res) = Tkapp_CallResult(e->self);
1236 }
1237 LEAVE_PYTHON
1238 done:
1239 /* Wake up calling thread. */
1240 Tcl_MutexLock(&call_mutex);
1241 Tcl_ConditionNotify(&e->done);
1242 Tcl_MutexUnlock(&call_mutex);
1243 return 1;
1244}
1245
1246/* This is the main entry point for calling a Tcl command.
1247 It supports three cases, with regard to threading:
1248 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1249 the context of the calling thread.
1250 2. Tcl is threaded, caller of the command is in the interpreter thread:
1251 Execute the command in the calling thread. Since the Tcl lock will
1252 not be used, we can merge that with case 1.
1253 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1254 the interpreter thread. Allocation of Tcl objects needs to occur in the
1255 interpreter thread, so we ship the PyObject* args to the target thread,
1256 and perform processing there. */
1257
1258static PyObject *
1259Tkapp_Call(PyObject *_self, PyObject *args)
1260{
1261 Tcl_Obj *objStore[ARGSZ];
1262 Tcl_Obj **objv = NULL;
1263 int objc, i;
1264 PyObject *res = NULL;
1265 TkappObject *self = (TkappObject*)_self;
1266 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1267 int flags = TCL_EVAL_DIRECT;
1268
Martin v. Löwisa9656492003-03-30 08:44:58 +00001269#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001270 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1271 /* We cannot call the command directly. Instead, we must
1272 marshal the parameters to the interpreter thread. */
1273 Tkapp_CallEvent *ev;
1274 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001275 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001276 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001277 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1278 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1279 ev->self = self;
1280 ev->args = args;
1281 ev->res = &res;
1282 ev->exc_type = &exc_type;
1283 ev->exc_value = &exc_value;
1284 ev->exc_tb = &exc_tb;
1285 ev->done = (Tcl_Condition)0;
1286
1287 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1288
1289 if (res == NULL) {
1290 if (exc_type)
1291 PyErr_Restore(exc_type, exc_value, exc_tb);
1292 else
1293 PyErr_SetObject(Tkinter_TclError, exc_value);
1294 }
1295 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001296 else
1297#endif
1298 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001299
1300 objv = Tkapp_CallArgs(args, objStore, &objc);
1301 if (!objv)
1302 return NULL;
1303
1304 ENTER_TCL
1305
1306 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1307
1308 ENTER_OVERLAP
1309
1310 if (i == TCL_ERROR)
1311 Tkinter_Error(_self);
1312 else
1313 res = Tkapp_CallResult(self);
1314
1315 LEAVE_OVERLAP_TCL
1316
1317 Tkapp_CallDeallocArgs(objv, objStore, objc);
1318 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001319 return res;
1320}
1321
1322
1323static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001324Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001325{
Guido van Rossum212643f1998-04-29 16:22:14 +00001326 /* Could do the same here as for Tkapp_Call(), but this is not used
1327 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1328 way for the user to do what all its Global* variants do (save and
1329 reset the scope pointer, call the local version, restore the saved
1330 scope pointer). */
1331
Guido van Rossum62320c91998-06-15 04:36:09 +00001332 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001333 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001334
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001335 CHECK_TCL_APPARTMENT;
1336
Guido van Rossum62320c91998-06-15 04:36:09 +00001337 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001338 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001339 int err;
1340 ENTER_TCL
1341 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001342 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001343 if (err == TCL_ERROR)
1344 res = Tkinter_Error(self);
1345 else
1346 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001347 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001348 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001349 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001350
1351 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001352}
1353
1354static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001355Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001356{
Barry Warsawfa701a81997-01-16 00:15:11 +00001357 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001358 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001359 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001360
Guido van Rossum43713e52000-02-29 13:59:29 +00001361 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001362 return NULL;
1363
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001364 CHECK_TCL_APPARTMENT;
1365
Guido van Rossum00d93061998-05-28 23:06:38 +00001366 ENTER_TCL
1367 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001368 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001369 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001370 res = Tkinter_Error(self);
1371 else
1372 res = PyString_FromString(Tkapp_Result(self));
1373 LEAVE_OVERLAP_TCL
1374 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001375}
1376
1377static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001378Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001379{
Barry Warsawfa701a81997-01-16 00:15:11 +00001380 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001381 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001382 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001383
Guido van Rossum43713e52000-02-29 13:59:29 +00001384 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001385 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001386
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001387 CHECK_TCL_APPARTMENT;
1388
Guido van Rossum00d93061998-05-28 23:06:38 +00001389 ENTER_TCL
1390 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001391 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001392 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001393 res = Tkinter_Error(self);
1394 else
1395 res = PyString_FromString(Tkapp_Result(self));
1396 LEAVE_OVERLAP_TCL
1397 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001398}
1399
1400static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001401Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001402{
Barry Warsawfa701a81997-01-16 00:15:11 +00001403 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001404 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001405 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001406
Guido van Rossum43713e52000-02-29 13:59:29 +00001407 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001408 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001409
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001410 CHECK_TCL_APPARTMENT;
1411
Guido van Rossum00d93061998-05-28 23:06:38 +00001412 ENTER_TCL
1413 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001414 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001415 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001416 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001417
Guido van Rossum62320c91998-06-15 04:36:09 +00001418 else
1419 res = PyString_FromString(Tkapp_Result(self));
1420 LEAVE_OVERLAP_TCL
1421 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001422}
1423
1424static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001425Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001426{
Barry Warsawfa701a81997-01-16 00:15:11 +00001427 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001428 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001429 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001430
Guido van Rossum35d43371997-08-02 00:09:09 +00001431 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001432 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001433
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001434 CHECK_TCL_APPARTMENT;
1435
Guido van Rossum00d93061998-05-28 23:06:38 +00001436 ENTER_TCL
1437 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001438 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001439 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001440 res = Tkinter_Error(self);
1441 else
1442 res = PyString_FromString(Tkapp_Result(self));
1443 LEAVE_OVERLAP_TCL
1444 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001445}
1446
1447static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001448Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001449{
Barry Warsawfa701a81997-01-16 00:15:11 +00001450 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001451
Guido van Rossum43713e52000-02-29 13:59:29 +00001452 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001453 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001454 CHECK_TCL_APPARTMENT;
1455
Guido van Rossum00d93061998-05-28 23:06:38 +00001456 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001457 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001458 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001459
Barry Warsawfa701a81997-01-16 00:15:11 +00001460 Py_INCREF(Py_None);
1461 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001462}
1463
Barry Warsawfa701a81997-01-16 00:15:11 +00001464
1465
Guido van Rossum18468821994-06-20 07:49:28 +00001466/** Tcl Variable **/
1467
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001468TCL_DECLARE_MUTEX(var_mutex)
1469
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001470typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001471typedef struct VarEvent {
1472 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001473 PyObject *self;
1474 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001475 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001476 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001477 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001478 PyObject **exc_type;
1479 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001480 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001481} VarEvent;
1482
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001483static int
1484varname_converter(PyObject *in, void *_out)
1485{
1486 char **out = (char**)_out;
1487 if (PyString_Check(in)) {
1488 *out = PyString_AsString(in);
1489 return 1;
1490 }
1491 if (PyTclObject_Check(in)) {
1492 *out = PyTclObject_TclString(in);
1493 return 1;
1494 }
1495 /* XXX: Should give diagnostics. */
1496 return 0;
1497}
1498
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001499void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001500var_perform(VarEvent *ev)
1501{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001502 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1503 if (!*(ev->res)) {
1504 PyObject *exc, *val, *tb;
1505 PyErr_Fetch(&exc, &val, &tb);
1506 PyErr_NormalizeException(&exc, &val, &tb);
1507 *(ev->exc_type) = exc;
1508 *(ev->exc_val) = val;
1509 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001510 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001511
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001512}
1513
1514static int
1515var_proc(VarEvent* ev, int flags)
1516{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001517 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001518 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001519 Tcl_MutexLock(&var_mutex);
1520 Tcl_ConditionNotify(&ev->cond);
1521 Tcl_MutexUnlock(&var_mutex);
1522 LEAVE_PYTHON
1523 return 1;
1524}
1525
1526static PyObject*
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001527var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001528{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001529 TkappObject *self = (TkappObject*)_self;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001530#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001531 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001532 TkappObject *self = (TkappObject*)_self;
1533 VarEvent *ev;
1534 PyObject *res, *exc_type, *exc_val;
1535
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536 /* The current thread is not the interpreter thread. Marshal
1537 the call to the interpreter thread, then wait for
1538 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001539 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001540 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001541
1542 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1543
1544 ev->self = _self;
1545 ev->args = args;
1546 ev->flags = flags;
1547 ev->func = func;
1548 ev->res = &res;
1549 ev->exc_type = &exc_type;
1550 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001551 ev->cond = NULL;
1552 ev->ev.proc = (Tcl_EventProc*)var_proc;
1553 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001554 if (!res) {
1555 PyErr_SetObject(exc_type, exc_val);
1556 Py_DECREF(exc_type);
1557 Py_DECREF(exc_val);
1558 return NULL;
1559 }
1560 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001561 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001562#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001563 /* Tcl is not threaded, or this is the interpreter thread. */
1564 return func(_self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001565}
1566
Guido van Rossum18468821994-06-20 07:49:28 +00001567static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001568SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001569{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001570 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001571 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001572 PyObject *res = NULL;
1573 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001574
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001575 if (PyArg_ParseTuple(args, "O&O:setvar",
1576 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001577 /* XXX Acquire tcl lock??? */
1578 newval = AsObj(newValue);
1579 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001580 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001581 ENTER_TCL
1582 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1583 newval, flags);
1584 ENTER_OVERLAP
1585 if (!ok)
1586 Tkinter_Error(self);
1587 else {
1588 res = Py_None;
1589 Py_INCREF(res);
1590 }
1591 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001592 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001593 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001594 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001595 if (PyArg_ParseTuple(args, "ssO:setvar",
1596 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001597 /* XXX must hold tcl lock already??? */
1598 newval = AsObj(newValue);
1599 ENTER_TCL
1600 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1601 ENTER_OVERLAP
1602 if (!ok)
1603 Tkinter_Error(self);
1604 else {
1605 res = Py_None;
1606 Py_INCREF(res);
1607 }
1608 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001609 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001610 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001611 return NULL;
1612 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001613 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001614 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001615}
1616
1617static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001618Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001619{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001620 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001621}
1622
1623static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001624Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001625{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001626 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001627}
1628
Barry Warsawfa701a81997-01-16 00:15:11 +00001629
1630
Guido van Rossum18468821994-06-20 07:49:28 +00001631static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001632GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001633{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001634 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001635 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001636 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001637
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001638 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1639 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001640 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001641
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001642 ENTER_TCL
1643 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1644 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001645 if (tres == NULL) {
1646 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1647 } else {
1648 if (((TkappObject*)self)->wantobjects) {
1649 res = FromObj(self, tres);
1650 }
1651 else {
1652 res = PyString_FromString(Tcl_GetString(tres));
1653 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001654 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001655 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001656 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001657}
1658
1659static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001660Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001661{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001662 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001663}
1664
1665static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001666Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001667{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001668 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001669}
1670
Barry Warsawfa701a81997-01-16 00:15:11 +00001671
1672
Guido van Rossum18468821994-06-20 07:49:28 +00001673static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001674UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001675{
Guido van Rossum35d43371997-08-02 00:09:09 +00001676 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001677 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001678 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001679
Guido van Rossum43713e52000-02-29 13:59:29 +00001680 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001681 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001682
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001683 ENTER_TCL
1684 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1685 ENTER_OVERLAP
1686 if (code == TCL_ERROR)
1687 res = Tkinter_Error(self);
1688 else {
1689 Py_INCREF(Py_None);
1690 res = Py_None;
1691 }
1692 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001693 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001694}
1695
1696static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001697Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001698{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001699 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001700}
1701
1702static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001703Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001704{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001705 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001706}
1707
Barry Warsawfa701a81997-01-16 00:15:11 +00001708
1709
Guido van Rossum18468821994-06-20 07:49:28 +00001710/** Tcl to Python **/
1711
1712static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001713Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001714{
Barry Warsawfa701a81997-01-16 00:15:11 +00001715 char *s;
1716 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001717
Martin v. Löwisffad6332002-11-26 09:28:05 +00001718 if (PyTuple_Size(args) == 1) {
1719 PyObject* o = PyTuple_GetItem(args, 0);
1720 if (PyInt_Check(o)) {
1721 Py_INCREF(o);
1722 return o;
1723 }
1724 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001725 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001726 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001727 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001728 return Tkinter_Error(self);
1729 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001730}
1731
1732static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001733Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001734{
Barry Warsawfa701a81997-01-16 00:15:11 +00001735 char *s;
1736 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001737
Martin v. Löwisffad6332002-11-26 09:28:05 +00001738 if (PyTuple_Size(args) == 1) {
1739 PyObject *o = PyTuple_GetItem(args, 0);
1740 if (PyFloat_Check(o)) {
1741 Py_INCREF(o);
1742 return o;
1743 }
1744 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001745 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001746 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001747 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001748 return Tkinter_Error(self);
1749 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001750}
1751
1752static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001753Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001754{
Barry Warsawfa701a81997-01-16 00:15:11 +00001755 char *s;
1756 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001757
Martin v. Löwisffad6332002-11-26 09:28:05 +00001758 if (PyTuple_Size(args) == 1) {
1759 PyObject *o = PyTuple_GetItem(args, 0);
1760 if (PyInt_Check(o)) {
1761 Py_INCREF(o);
1762 return o;
1763 }
1764 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001765 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001766 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001767 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1768 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001769 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001770}
1771
1772static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001773Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001774{
Barry Warsawfa701a81997-01-16 00:15:11 +00001775 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001776 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001777 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001778
Guido van Rossum43713e52000-02-29 13:59:29 +00001779 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001780 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001781
1782 CHECK_TCL_APPARTMENT;
1783
Guido van Rossum00d93061998-05-28 23:06:38 +00001784 ENTER_TCL
1785 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001786 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001787 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001788 res = Tkinter_Error(self);
1789 else
1790 res = Py_BuildValue("s", Tkapp_Result(self));
1791 LEAVE_OVERLAP_TCL
1792 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001793}
1794
1795static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001796Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001797{
Barry Warsawfa701a81997-01-16 00:15:11 +00001798 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001799 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001800 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001801 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001802
Guido van Rossum43713e52000-02-29 13:59:29 +00001803 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001804 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001805
1806 CHECK_TCL_APPARTMENT;
1807
Guido van Rossum00d93061998-05-28 23:06:38 +00001808 ENTER_TCL
1809 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001810 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001811 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001812 res = Tkinter_Error(self);
1813 else
1814 res = Py_BuildValue("l", v);
1815 LEAVE_OVERLAP_TCL
1816 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001817}
1818
1819static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001820Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001821{
Barry Warsawfa701a81997-01-16 00:15:11 +00001822 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001823 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001824 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001825 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001826
Guido van Rossum43713e52000-02-29 13:59:29 +00001827 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001828 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001829 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001830 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001831 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001832 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001833 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001834 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001835 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001836 res = Tkinter_Error(self);
1837 else
1838 res = Py_BuildValue("d", v);
1839 LEAVE_OVERLAP_TCL
1840 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001841}
1842
1843static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001844Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001845{
Barry Warsawfa701a81997-01-16 00:15:11 +00001846 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001847 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001848 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001849 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001850
Guido van Rossum43713e52000-02-29 13:59:29 +00001851 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001852 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001853 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001854 ENTER_TCL
1855 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001856 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001857 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001858 res = Tkinter_Error(self);
1859 else
1860 res = Py_BuildValue("i", v);
1861 LEAVE_OVERLAP_TCL
1862 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001863}
1864
Barry Warsawfa701a81997-01-16 00:15:11 +00001865
1866
Guido van Rossum18468821994-06-20 07:49:28 +00001867static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001868Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001869{
Barry Warsawfa701a81997-01-16 00:15:11 +00001870 char *list;
1871 int argc;
1872 char **argv;
1873 PyObject *v;
1874 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001875
Martin v. Löwisffad6332002-11-26 09:28:05 +00001876 if (PyTuple_Size(args) == 1) {
1877 v = PyTuple_GetItem(args, 0);
1878 if (PyTuple_Check(v)) {
1879 Py_INCREF(v);
1880 return v;
1881 }
1882 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001883 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001884 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001885
Neal Norwitzd1c55102003-05-29 00:17:03 +00001886 if (Tcl_SplitList(Tkapp_Interp(self), list,
1887 &argc, &argv) == TCL_ERROR) {
1888 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001889 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001890 }
Guido van Rossum18468821994-06-20 07:49:28 +00001891
Barry Warsawfa701a81997-01-16 00:15:11 +00001892 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001893 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001894
Barry Warsawfa701a81997-01-16 00:15:11 +00001895 for (i = 0; i < argc; i++) {
1896 PyObject *s = PyString_FromString(argv[i]);
1897 if (!s || PyTuple_SetItem(v, i, s)) {
1898 Py_DECREF(v);
1899 v = NULL;
1900 goto finally;
1901 }
1902 }
Guido van Rossum18468821994-06-20 07:49:28 +00001903
Barry Warsawfa701a81997-01-16 00:15:11 +00001904 finally:
1905 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001906 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001907 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001908}
1909
1910static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001911Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001912{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001913 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001914 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001915
Martin v. Löwisffad6332002-11-26 09:28:05 +00001916 if (PyTuple_Size(args) == 1) {
1917 PyObject* o = PyTuple_GetItem(args, 0);
1918 if (PyTuple_Check(o)) {
1919 o = SplitObj(o);
1920 return o;
1921 }
1922 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001923 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001924 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001925 v = Split(list);
1926 PyMem_Free(list);
1927 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001928}
1929
1930static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001931Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001932{
Barry Warsawfa701a81997-01-16 00:15:11 +00001933 char *s = Merge(args);
1934 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001935
Barry Warsawfa701a81997-01-16 00:15:11 +00001936 if (s) {
1937 res = PyString_FromString(s);
1938 ckfree(s);
1939 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001940
1941 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001942}
1943
Barry Warsawfa701a81997-01-16 00:15:11 +00001944
1945
Guido van Rossum18468821994-06-20 07:49:28 +00001946/** Tcl Command **/
1947
Guido van Rossum00d93061998-05-28 23:06:38 +00001948/* Client data struct */
1949typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001950 PyObject *self;
1951 PyObject *func;
1952} PythonCmd_ClientData;
1953
1954static int
Fred Drake509d79a2000-07-08 04:04:38 +00001955PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001956{
1957 errorInCmd = 1;
1958 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1959 LEAVE_PYTHON
1960 return TCL_ERROR;
1961}
1962
Guido van Rossum18468821994-06-20 07:49:28 +00001963/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001964 * function or method.
1965 */
Guido van Rossum18468821994-06-20 07:49:28 +00001966static int
Fred Drake509d79a2000-07-08 04:04:38 +00001967PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001968{
Guido van Rossum00d93061998-05-28 23:06:38 +00001969 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001970 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001971 int i, rv;
1972 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001973
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001974 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001975
Barry Warsawfa701a81997-01-16 00:15:11 +00001976 /* TBD: no error checking here since we know, via the
1977 * Tkapp_CreateCommand() that the client data is a two-tuple
1978 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001979 self = data->self;
1980 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001981
Barry Warsawfa701a81997-01-16 00:15:11 +00001982 /* Create argument list (argv1, ..., argvN) */
1983 if (!(arg = PyTuple_New(argc - 1)))
1984 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001985
Barry Warsawfa701a81997-01-16 00:15:11 +00001986 for (i = 0; i < (argc - 1); i++) {
1987 PyObject *s = PyString_FromString(argv[i + 1]);
1988 if (!s || PyTuple_SetItem(arg, i, s)) {
1989 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001990 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001991 }
1992 }
1993 res = PyEval_CallObject(func, arg);
1994 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001995
Barry Warsawfa701a81997-01-16 00:15:11 +00001996 if (res == NULL)
1997 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001998
Barry Warsawfa701a81997-01-16 00:15:11 +00001999 if (!(tmp = PyList_New(0))) {
2000 Py_DECREF(res);
2001 return PythonCmd_Error(interp);
2002 }
2003
Guido van Rossum2834b972000-10-06 16:58:26 +00002004 s = AsString(res, tmp);
2005 if (s == NULL) {
2006 rv = PythonCmd_Error(interp);
2007 }
2008 else {
2009 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
2010 rv = TCL_OK;
2011 }
2012
Barry Warsawfa701a81997-01-16 00:15:11 +00002013 Py_DECREF(res);
2014 Py_DECREF(tmp);
2015
Guido van Rossum00d93061998-05-28 23:06:38 +00002016 LEAVE_PYTHON
2017
Guido van Rossum2834b972000-10-06 16:58:26 +00002018 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002019}
2020
2021static void
Fred Drake509d79a2000-07-08 04:04:38 +00002022PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002023{
Guido van Rossum00d93061998-05-28 23:06:38 +00002024 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2025
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002026 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002027 Py_XDECREF(data->self);
2028 Py_XDECREF(data->func);
2029 PyMem_DEL(data);
2030 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002031}
2032
Barry Warsawfa701a81997-01-16 00:15:11 +00002033
2034
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002035
2036TCL_DECLARE_MUTEX(command_mutex)
2037
2038typedef struct CommandEvent{
2039 Tcl_Event ev;
2040 Tcl_Interp* interp;
2041 char *name;
2042 int create;
2043 int *status;
2044 ClientData *data;
2045 Tcl_Condition done;
2046} CommandEvent;
2047
2048static int
2049Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002050{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002051 if (ev->create)
2052 *ev->status = Tcl_CreateCommand(
2053 ev->interp, ev->name, PythonCmd,
2054 ev->data, PythonCmdDelete) == NULL;
2055 else
2056 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2057 Tcl_MutexLock(&command_mutex);
2058 Tcl_ConditionNotify(&ev->done);
2059 Tcl_MutexUnlock(&command_mutex);
2060 return 1;
2061}
2062
2063static PyObject *
2064Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2065{
2066 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002067 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002068 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002069 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002070 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002071
Guido van Rossum43713e52000-02-29 13:59:29 +00002072 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002073 return NULL;
2074 if (!PyCallable_Check(func)) {
2075 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002076 return NULL;
2077 }
Guido van Rossum18468821994-06-20 07:49:28 +00002078
Martin v. Löwisa9656492003-03-30 08:44:58 +00002079#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002080 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002081 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002082 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002083#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002084
Guido van Rossum00d93061998-05-28 23:06:38 +00002085 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002086 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002087 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002088 Py_XINCREF(self);
2089 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002090 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002091 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002092
2093 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2094 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2095 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2096 ev->interp = self->interp;
2097 ev->create = 1;
2098 ev->name = cmdName;
2099 ev->data = (ClientData)data;
2100 ev->status = &err;
2101 ev->done = NULL;
2102 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2103 }
2104 else {
2105 ENTER_TCL
2106 err = Tcl_CreateCommand(
2107 Tkapp_Interp(self), cmdName, PythonCmd,
2108 (ClientData)data, PythonCmdDelete) == NULL;
2109 LEAVE_TCL
2110 }
2111 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002112 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002113 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002114 return NULL;
2115 }
Guido van Rossum18468821994-06-20 07:49:28 +00002116
Barry Warsawfa701a81997-01-16 00:15:11 +00002117 Py_INCREF(Py_None);
2118 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002119}
2120
Barry Warsawfa701a81997-01-16 00:15:11 +00002121
2122
Guido van Rossum18468821994-06-20 07:49:28 +00002123static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002124Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002125{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002126 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002127 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002128 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002129
Guido van Rossum43713e52000-02-29 13:59:29 +00002130 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002131 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002132 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2133 CommandEvent *ev;
2134 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2135 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2136 ev->interp = self->interp;
2137 ev->create = 0;
2138 ev->name = cmdName;
2139 ev->status = &err;
2140 ev->done = NULL;
2141 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2142 &command_mutex);
2143 }
2144 else {
2145 ENTER_TCL
2146 err = Tcl_DeleteCommand(self->interp, cmdName);
2147 LEAVE_TCL
2148 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002149 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002150 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2151 return NULL;
2152 }
2153 Py_INCREF(Py_None);
2154 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002155}
2156
Barry Warsawfa701a81997-01-16 00:15:11 +00002157
2158
Guido van Rossum00d93061998-05-28 23:06:38 +00002159#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002160/** File Handler **/
2161
Guido van Rossum00d93061998-05-28 23:06:38 +00002162typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002163 PyObject *func;
2164 PyObject *file;
2165 int id;
2166 struct _fhcdata *next;
2167} FileHandler_ClientData;
2168
2169static FileHandler_ClientData *HeadFHCD;
2170
2171static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002172NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002173{
2174 FileHandler_ClientData *p;
2175 p = PyMem_NEW(FileHandler_ClientData, 1);
2176 if (p != NULL) {
2177 Py_XINCREF(func);
2178 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002179 p->func = func;
2180 p->file = file;
2181 p->id = id;
2182 p->next = HeadFHCD;
2183 HeadFHCD = p;
2184 }
2185 return p;
2186}
2187
2188static void
Fred Drake509d79a2000-07-08 04:04:38 +00002189DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002190{
2191 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002192
2193 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002194 while ((p = *pp) != NULL) {
2195 if (p->id == id) {
2196 *pp = p->next;
2197 Py_XDECREF(p->func);
2198 Py_XDECREF(p->file);
2199 PyMem_DEL(p);
2200 }
2201 else
2202 pp = &p->next;
2203 }
2204}
2205
Guido van Rossuma597dde1995-01-10 20:56:29 +00002206static void
Fred Drake509d79a2000-07-08 04:04:38 +00002207FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002208{
Guido van Rossum00d93061998-05-28 23:06:38 +00002209 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002210 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002211
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002212 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002213 func = data->func;
2214 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002215
Barry Warsawfa701a81997-01-16 00:15:11 +00002216 arg = Py_BuildValue("(Oi)", file, (long) mask);
2217 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002218 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002219
2220 if (res == NULL) {
2221 errorInCmd = 1;
2222 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2223 }
2224 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002225 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002226}
2227
Guido van Rossum18468821994-06-20 07:49:28 +00002228static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002229Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2230 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002231{
Guido van Rossum00d93061998-05-28 23:06:38 +00002232 FileHandler_ClientData *data;
2233 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002234 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002235
Guido van Rossum2834b972000-10-06 16:58:26 +00002236 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2237 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002238 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002239
Martin v. Löwisa9656492003-03-30 08:44:58 +00002240#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002241 if (!self && !tcl_lock) {
2242 /* We don't have the Tcl lock since Tcl is threaded. */
2243 PyErr_SetString(PyExc_RuntimeError,
2244 "_tkinter.createfilehandler not supported "
2245 "for threaded Tcl");
2246 return NULL;
2247 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002248#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002249
2250 if (self) {
2251 CHECK_TCL_APPARTMENT;
2252 }
2253
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002254 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002255 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002256 return NULL;
2257 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002258 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002259 return NULL;
2260 }
2261
Guido van Rossuma80649b2000-03-28 20:07:05 +00002262 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002263 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002264 return NULL;
2265
Barry Warsawfa701a81997-01-16 00:15:11 +00002266 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002267 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002268 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002269 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002270 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002271 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002272}
2273
2274static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002275Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002276{
Barry Warsawfa701a81997-01-16 00:15:11 +00002277 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002278 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002279
Guido van Rossum43713e52000-02-29 13:59:29 +00002280 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002281 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002282
Martin v. Löwisa9656492003-03-30 08:44:58 +00002283#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002284 if (!self && !tcl_lock) {
2285 /* We don't have the Tcl lock since Tcl is threaded. */
2286 PyErr_SetString(PyExc_RuntimeError,
2287 "_tkinter.deletefilehandler not supported "
2288 "for threaded Tcl");
2289 return NULL;
2290 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002291#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002292
2293 if (self) {
2294 CHECK_TCL_APPARTMENT;
2295 }
2296
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002297 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002298 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002299 return NULL;
2300
Guido van Rossuma80649b2000-03-28 20:07:05 +00002301 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002302
Barry Warsawfa701a81997-01-16 00:15:11 +00002303 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002304 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002305 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002306 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002307 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002308 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002309}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002310#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002311
Barry Warsawfa701a81997-01-16 00:15:11 +00002312
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002313/**** Tktt Object (timer token) ****/
2314
Jeremy Hylton938ace62002-07-17 16:30:39 +00002315static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002316
Guido van Rossum00d93061998-05-28 23:06:38 +00002317typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002318 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002319 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002320 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002321} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002322
2323static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002324Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002325{
Barry Warsawfa701a81997-01-16 00:15:11 +00002326 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002327 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002328
Guido van Rossum43713e52000-02-29 13:59:29 +00002329 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002330 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002331 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002332 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002333 v->token = NULL;
2334 }
2335 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002336 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002337 Py_DECREF(func);
2338 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002339 }
2340 Py_INCREF(Py_None);
2341 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002342}
2343
2344static PyMethodDef Tktt_methods[] =
2345{
Neal Norwitzb0493252002-03-31 14:44:22 +00002346 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002347 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002348};
2349
2350static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002351Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002352{
Barry Warsawfa701a81997-01-16 00:15:11 +00002353 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002354
Guido van Rossumb18618d2000-05-03 23:44:39 +00002355 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002356 if (v == NULL)
2357 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002358
Guido van Rossum00d93061998-05-28 23:06:38 +00002359 Py_INCREF(func);
2360 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002361 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002362
2363 /* Extra reference, deleted when called or when handler is deleted */
2364 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002365 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002366}
2367
2368static void
Fred Drake509d79a2000-07-08 04:04:38 +00002369Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002370{
Guido van Rossum00d93061998-05-28 23:06:38 +00002371 TkttObject *v = (TkttObject *)self;
2372 PyObject *func = v->func;
2373
2374 Py_XDECREF(func);
2375
Guido van Rossumb18618d2000-05-03 23:44:39 +00002376 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002377}
2378
Guido van Rossum597ac201998-05-12 14:36:19 +00002379static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002380Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002381{
Barry Warsawfa701a81997-01-16 00:15:11 +00002382 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002383 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002384
Tim Peters885d4572001-11-28 20:27:42 +00002385 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002386 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002387 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002388}
2389
2390static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002391Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002392{
Barry Warsawfa701a81997-01-16 00:15:11 +00002393 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002394}
2395
2396static PyTypeObject Tktt_Type =
2397{
Guido van Rossum35d43371997-08-02 00:09:09 +00002398 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002399 0, /*ob_size */
2400 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002401 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002402 0, /*tp_itemsize */
2403 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002404 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002405 Tktt_GetAttr, /*tp_getattr */
2406 0, /*tp_setattr */
2407 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002408 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002409 0, /*tp_as_number */
2410 0, /*tp_as_sequence */
2411 0, /*tp_as_mapping */
2412 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002413};
2414
Barry Warsawfa701a81997-01-16 00:15:11 +00002415
2416
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002417/** Timer Handler **/
2418
2419static void
Fred Drake509d79a2000-07-08 04:04:38 +00002420TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002421{
Guido van Rossum00d93061998-05-28 23:06:38 +00002422 TkttObject *v = (TkttObject *)clientData;
2423 PyObject *func = v->func;
2424 PyObject *res;
2425
2426 if (func == NULL)
2427 return;
2428
2429 v->func = NULL;
2430
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002431 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002432
2433 res = PyEval_CallObject(func, NULL);
2434 Py_DECREF(func);
2435 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002436
Barry Warsawfa701a81997-01-16 00:15:11 +00002437 if (res == NULL) {
2438 errorInCmd = 1;
2439 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2440 }
2441 else
2442 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002443
2444 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002445}
2446
2447static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002448Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002449{
Barry Warsawfa701a81997-01-16 00:15:11 +00002450 int milliseconds;
2451 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002452 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002453
Guido van Rossum2834b972000-10-06 16:58:26 +00002454 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2455 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002456 return NULL;
2457 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002458 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002459 return NULL;
2460 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002461
Martin v. Löwisa9656492003-03-30 08:44:58 +00002462#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002463 if (!self && !tcl_lock) {
2464 /* We don't have the Tcl lock since Tcl is threaded. */
2465 PyErr_SetString(PyExc_RuntimeError,
2466 "_tkinter.createtimerhandler not supported "
2467 "for threaded Tcl");
2468 return NULL;
2469 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002470#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002471
2472 if (self) {
2473 CHECK_TCL_APPARTMENT;
2474 }
2475
Guido van Rossum00d93061998-05-28 23:06:38 +00002476 v = Tktt_New(func);
2477 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2478 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002479
Guido van Rossum00d93061998-05-28 23:06:38 +00002480 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002481}
2482
Barry Warsawfa701a81997-01-16 00:15:11 +00002483
Guido van Rossum18468821994-06-20 07:49:28 +00002484/** Event Loop **/
2485
Guido van Rossum18468821994-06-20 07:49:28 +00002486static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002487Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002488{
Barry Warsawfa701a81997-01-16 00:15:11 +00002489 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002490 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002491#ifdef WITH_THREAD
2492 PyThreadState *tstate = PyThreadState_Get();
2493#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002494
Guido van Rossum43713e52000-02-29 13:59:29 +00002495 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002496 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002497
Martin v. Löwisa9656492003-03-30 08:44:58 +00002498#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002499 if (!self && !tcl_lock) {
2500 /* We don't have the Tcl lock since Tcl is threaded. */
2501 PyErr_SetString(PyExc_RuntimeError,
2502 "_tkinter.mainloop not supported "
2503 "for threaded Tcl");
2504 return NULL;
2505 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002506#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002507
2508 if (self) {
2509 CHECK_TCL_APPARTMENT;
2510 self->dispatching = 1;
2511 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002512
Barry Warsawfa701a81997-01-16 00:15:11 +00002513 quitMainLoop = 0;
2514 while (Tk_GetNumMainWindows() > threshold &&
2515 !quitMainLoop &&
2516 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002517 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002518 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002519
2520#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002521 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002522 /* Allow other Python threads to run. */
2523 ENTER_TCL
2524 result = Tcl_DoOneEvent(0);
2525 LEAVE_TCL
2526 }
2527 else {
2528 Py_BEGIN_ALLOW_THREADS
2529 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2530 tcl_tstate = tstate;
2531 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2532 tcl_tstate = NULL;
2533 if(tcl_lock)PyThread_release_lock(tcl_lock);
2534 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002535 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002536 Py_END_ALLOW_THREADS
2537 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002538#else
2539 result = Tcl_DoOneEvent(0);
2540#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002541
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002542 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002543 if (self)
2544 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002545 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002546 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002547 if (result < 0)
2548 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002549 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002550 if (self)
2551 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002552 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002553
Barry Warsawfa701a81997-01-16 00:15:11 +00002554 if (errorInCmd) {
2555 errorInCmd = 0;
2556 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2557 excInCmd = valInCmd = trbInCmd = NULL;
2558 return NULL;
2559 }
2560 Py_INCREF(Py_None);
2561 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002562}
2563
2564static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002565Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002566{
Guido van Rossum35d43371997-08-02 00:09:09 +00002567 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002568 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002569
Guido van Rossum43713e52000-02-29 13:59:29 +00002570 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002571 return NULL;
2572
Guido van Rossum00d93061998-05-28 23:06:38 +00002573 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002574 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002575 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002576 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002577}
2578
2579static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002580Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002581{
2582
Guido van Rossum43713e52000-02-29 13:59:29 +00002583 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002584 return NULL;
2585
2586 quitMainLoop = 1;
2587 Py_INCREF(Py_None);
2588 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002589}
2590
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002591static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002592Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002593{
2594
Guido van Rossum43713e52000-02-29 13:59:29 +00002595 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002596 return NULL;
2597
2598 return PyInt_FromLong((long)Tkapp_Interp(self));
2599}
2600
David Aschere2b4b322004-02-18 05:59:53 +00002601static PyObject *
2602Tkapp_TkInit(PyObject *self, PyObject *args)
2603{
2604 Tcl_Interp *interp = Tkapp_Interp(self);
Neal Norwitz44dbae82004-02-19 02:44:22 +00002605 Tk_Window main_window;
David Aschere2b4b322004-02-18 05:59:53 +00002606 const char * _tk_exists = NULL;
2607 PyObject *res = NULL;
2608 int err;
Neal Norwitz44dbae82004-02-19 02:44:22 +00002609 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002610
2611 /* We want to guard against calling Tk_Init() multiple times */
2612 CHECK_TCL_APPARTMENT;
2613 ENTER_TCL
2614 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2615 ENTER_OVERLAP
2616 if (err == TCL_ERROR) {
2617 res = Tkinter_Error(self);
2618 } else {
2619 _tk_exists = Tkapp_Result(self);
2620 }
2621 LEAVE_OVERLAP_TCL
2622 if (err == TCL_ERROR) {
2623 return NULL;
2624 }
2625 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2626 if (Tk_Init(interp) == TCL_ERROR) {
2627 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2628 return NULL;
2629 }
2630 }
2631 Py_INCREF(Py_None);
2632 return Py_None;
2633}
Barry Warsawfa701a81997-01-16 00:15:11 +00002634
Martin v. Löwisffad6332002-11-26 09:28:05 +00002635static PyObject *
2636Tkapp_WantObjects(PyObject *self, PyObject *args)
2637{
2638
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002639 int wantobjects = -1;
2640 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002641 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002642 if (wantobjects == -1)
2643 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002644 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002645
2646 Py_INCREF(Py_None);
2647 return Py_None;
2648}
2649
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002650static PyObject *
2651Tkapp_WillDispatch(PyObject *self, PyObject *args)
2652{
2653
2654 ((TkappObject*)self)->dispatching = 1;
2655
2656 Py_INCREF(Py_None);
2657 return Py_None;
2658}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002659
Barry Warsawfa701a81997-01-16 00:15:11 +00002660
Guido van Rossum18468821994-06-20 07:49:28 +00002661/**** Tkapp Method List ****/
2662
2663static PyMethodDef Tkapp_methods[] =
2664{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002665 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002666 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002667 {"call", Tkapp_Call, METH_OLDARGS},
2668 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2669 {"eval", Tkapp_Eval, METH_VARARGS},
2670 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2671 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2672 {"record", Tkapp_Record, METH_VARARGS},
2673 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2674 {"setvar", Tkapp_SetVar, METH_VARARGS},
2675 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2676 {"getvar", Tkapp_GetVar, METH_VARARGS},
2677 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2678 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2679 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2680 {"getint", Tkapp_GetInt, METH_VARARGS},
2681 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2682 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2683 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2684 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2685 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2686 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2687 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2688 {"split", Tkapp_Split, METH_VARARGS},
2689 {"merge", Tkapp_Merge, METH_OLDARGS},
2690 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2691 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002692#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002693 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2694 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002695#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002696 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2697 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2698 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2699 {"quit", Tkapp_Quit, METH_VARARGS},
2700 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Neal Norwitz44dbae82004-02-19 02:44:22 +00002701 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002702 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002703};
2704
Barry Warsawfa701a81997-01-16 00:15:11 +00002705
2706
Guido van Rossum18468821994-06-20 07:49:28 +00002707/**** Tkapp Type Methods ****/
2708
2709static void
Fred Drake509d79a2000-07-08 04:04:38 +00002710Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002711{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002712 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002713 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002714 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002715 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002716 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002717 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002718}
2719
2720static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002721Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002722{
Guido van Rossum35d43371997-08-02 00:09:09 +00002723 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002724}
2725
2726static PyTypeObject Tkapp_Type =
2727{
Guido van Rossum35d43371997-08-02 00:09:09 +00002728 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002729 0, /*ob_size */
2730 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002731 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002732 0, /*tp_itemsize */
2733 Tkapp_Dealloc, /*tp_dealloc */
2734 0, /*tp_print */
2735 Tkapp_GetAttr, /*tp_getattr */
2736 0, /*tp_setattr */
2737 0, /*tp_compare */
2738 0, /*tp_repr */
2739 0, /*tp_as_number */
2740 0, /*tp_as_sequence */
2741 0, /*tp_as_mapping */
2742 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002743};
2744
Barry Warsawfa701a81997-01-16 00:15:11 +00002745
2746
Guido van Rossum18468821994-06-20 07:49:28 +00002747/**** Tkinter Module ****/
2748
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002749typedef struct {
2750 PyObject* tuple;
2751 int size; /* current size */
2752 int maxsize; /* allocated size */
2753} FlattenContext;
2754
2755static int
2756_bump(FlattenContext* context, int size)
2757{
Guido van Rossum2834b972000-10-06 16:58:26 +00002758 /* expand tuple to hold (at least) size new items.
2759 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002760
2761 int maxsize = context->maxsize * 2;
2762
2763 if (maxsize < context->size + size)
2764 maxsize = context->size + size;
2765
2766 context->maxsize = maxsize;
2767
Tim Peters4324aa32001-05-28 22:30:08 +00002768 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002769}
2770
2771static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002772_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002773{
2774 /* add tuple or list to argument tuple (recursively) */
2775
2776 int i, size;
2777
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002778 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002779 PyErr_SetString(PyExc_ValueError,
2780 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002781 return 0;
2782 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002783 size = PyList_GET_SIZE(item);
2784 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002785 if (context->size + size > context->maxsize &&
2786 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002787 return 0;
2788 /* copy items to output tuple */
2789 for (i = 0; i < size; i++) {
2790 PyObject *o = PyList_GET_ITEM(item, i);
2791 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002792 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002793 return 0;
2794 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002795 if (context->size + 1 > context->maxsize &&
2796 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002797 return 0;
2798 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002799 PyTuple_SET_ITEM(context->tuple,
2800 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002801 }
2802 }
2803 } else if (PyTuple_Check(item)) {
2804 /* same, for tuples */
2805 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002806 if (context->size + size > context->maxsize &&
2807 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002808 return 0;
2809 for (i = 0; i < size; i++) {
2810 PyObject *o = PyTuple_GET_ITEM(item, i);
2811 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002812 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002813 return 0;
2814 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002815 if (context->size + 1 > context->maxsize &&
2816 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002817 return 0;
2818 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002819 PyTuple_SET_ITEM(context->tuple,
2820 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002821 }
2822 }
2823 } else {
2824 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2825 return 0;
2826 }
2827 return 1;
2828}
2829
2830static PyObject *
2831Tkinter_Flatten(PyObject* self, PyObject* args)
2832{
2833 FlattenContext context;
2834 PyObject* item;
2835
2836 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2837 return NULL;
2838
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002839 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002840 if (context.maxsize <= 0)
2841 return PyTuple_New(0);
2842
2843 context.tuple = PyTuple_New(context.maxsize);
2844 if (!context.tuple)
2845 return NULL;
2846
2847 context.size = 0;
2848
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002849 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002850 return NULL;
2851
Tim Peters4324aa32001-05-28 22:30:08 +00002852 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002853 return NULL;
2854
2855 return context.tuple;
2856}
2857
Guido van Rossum18468821994-06-20 07:49:28 +00002858static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002859Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002860{
Barry Warsawfa701a81997-01-16 00:15:11 +00002861 char *screenName = NULL;
2862 char *baseName = NULL;
2863 char *className = NULL;
2864 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002865 int wantobjects = 0;
David Aschere2b4b322004-02-18 05:59:53 +00002866 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002867 int sync = 0; /* pass -sync to wish */
2868 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002869
Guido van Rossum35d43371997-08-02 00:09:09 +00002870 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002871 if (baseName != NULL)
2872 baseName++;
2873 else
2874 baseName = Py_GetProgramName();
2875 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002876
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002877 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002878 &screenName, &baseName, &className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002879 &interactive, &wantobjects, &wantTk,
2880 &sync, &use))
Barry Warsawfa701a81997-01-16 00:15:11 +00002881 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002882
Barry Warsawfa701a81997-01-16 00:15:11 +00002883 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002884 interactive, wantobjects, wantTk,
2885 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002886}
2887
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002888static PyObject *
2889Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2890{
2891 int new_val;
2892 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2893 return NULL;
2894 if (new_val < 0) {
2895 PyErr_SetString(PyExc_ValueError,
2896 "busywaitinterval must be >= 0");
2897 return NULL;
2898 }
2899 Tkinter_busywaitinterval = new_val;
2900 Py_INCREF(Py_None);
2901 return Py_None;
2902}
2903
2904static char setbusywaitinterval_doc[] =
2905"setbusywaitinterval(n) -> None\n\
2906\n\
2907Set the busy-wait interval in milliseconds between successive\n\
2908calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2909It should be set to a divisor of the maximum time between\n\
2910frames in an animation.";
2911
2912static PyObject *
2913Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2914{
2915 return PyInt_FromLong(Tkinter_busywaitinterval);
2916}
2917
2918static char getbusywaitinterval_doc[] =
2919"getbusywaitinterval() -> int\n\
2920\n\
2921Return the current busy-wait interval between successive\n\
2922calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2923
Guido van Rossum18468821994-06-20 07:49:28 +00002924static PyMethodDef moduleMethods[] =
2925{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002926 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2927 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002928#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002929 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2930 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002931#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002932 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2933 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2934 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2935 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002936 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2937 setbusywaitinterval_doc},
2938 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2939 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002940 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002941};
2942
Guido van Rossum7bf15641998-05-22 18:28:17 +00002943#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002944
2945static int stdin_ready = 0;
2946
Guido van Rossumad4db171998-06-13 13:56:28 +00002947#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002948static void
Fred Drake509d79a2000-07-08 04:04:38 +00002949MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002950{
2951 stdin_ready = 1;
2952}
Guido van Rossumad4db171998-06-13 13:56:28 +00002953#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002954
Martin v. Löwisa9656492003-03-30 08:44:58 +00002955#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002956static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002957#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002958
Guido van Rossum18468821994-06-20 07:49:28 +00002959static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002960EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002961{
Guido van Rossumad4db171998-06-13 13:56:28 +00002962#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002963 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002964#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002965#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002966 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002967#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002968 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002969 errorInCmd = 0;
2970#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002971 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002972 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002973#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002974 while (!errorInCmd && !stdin_ready) {
2975 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002976#ifdef MS_WINDOWS
2977 if (_kbhit()) {
2978 stdin_ready = 1;
2979 break;
2980 }
2981#endif
2982#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002983 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002984 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002985 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002986
Guido van Rossum00d93061998-05-28 23:06:38 +00002987 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002988
2989 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002990 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002991 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002992 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002993 Py_END_ALLOW_THREADS
2994#else
2995 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002996#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002997
2998 if (result < 0)
2999 break;
3000 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003001#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00003002 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003003#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003004 if (errorInCmd) {
3005 errorInCmd = 0;
3006 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3007 excInCmd = valInCmd = trbInCmd = NULL;
3008 PyErr_Print();
3009 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003010#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00003011 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003012#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003013 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003014}
Guido van Rossum18468821994-06-20 07:49:28 +00003015
Guido van Rossum00d93061998-05-28 23:06:38 +00003016#endif
3017
Guido van Rossum7bf15641998-05-22 18:28:17 +00003018static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003019EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003020{
Guido van Rossum00d93061998-05-28 23:06:38 +00003021#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003022 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003023#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003024 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003025#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003026 PyOS_InputHook = EventHook;
3027 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003028#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003029}
3030
3031static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003032DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003033{
Guido van Rossum00d93061998-05-28 23:06:38 +00003034#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003035 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3036 PyOS_InputHook = NULL;
3037 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003038#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003039}
3040
Barry Warsawfa701a81997-01-16 00:15:11 +00003041
3042/* all errors will be checked in one fell swoop in init_tkinter() */
3043static void
Fred Drake509d79a2000-07-08 04:04:38 +00003044ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003045{
3046 PyObject *v = PyInt_FromLong(val);
3047 if (v) {
3048 PyDict_SetItemString(d, name, v);
3049 Py_DECREF(v);
3050 }
3051}
3052static void
Fred Drake509d79a2000-07-08 04:04:38 +00003053ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003054{
3055 PyObject *v = PyString_FromString(val);
3056 if (v) {
3057 PyDict_SetItemString(d, name, v);
3058 Py_DECREF(v);
3059 }
3060}
3061
3062
Mark Hammond62b1ab12002-07-23 06:31:15 +00003063PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003064init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003065{
Barry Warsawfa701a81997-01-16 00:15:11 +00003066 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003067
Barry Warsawfa701a81997-01-16 00:15:11 +00003068 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003069
3070#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003071 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003072#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003073
Barry Warsawfa701a81997-01-16 00:15:11 +00003074 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00003075
Barry Warsawfa701a81997-01-16 00:15:11 +00003076 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003077 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003078 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003079
Guido van Rossum35d43371997-08-02 00:09:09 +00003080 ins_long(d, "READABLE", TCL_READABLE);
3081 ins_long(d, "WRITABLE", TCL_WRITABLE);
3082 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3083 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3084 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3085 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3086 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3087 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3088 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003089 ins_string(d, "TK_VERSION", TK_VERSION);
3090 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003091
Guido van Rossum83551bf1997-09-13 00:44:23 +00003092 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003093
3094 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003095 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3096
Martin v. Löwisffad6332002-11-26 09:28:05 +00003097 PyTclObject_Type.ob_type = &PyType_Type;
3098 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003099
3100#ifdef TK_AQUA
3101 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3102 * start waking up. Note that Tcl_FindExecutable will do this, this
3103 * code must be above it! The original warning from
3104 * tkMacOSXAppInit.c is copied below.
3105 *
3106 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3107 * Tcl interpreter for now. It probably should work to do this
3108 * in the other order, but for now it doesn't seem to.
3109 *
3110 */
3111 Tk_MacOSXSetupTkNotifier();
3112#endif
3113
3114
Guido van Rossume187b0e2000-03-27 21:46:29 +00003115 /* This helps the dynamic loader; in Unicode aware Tcl versions
3116 it also helps Tcl find its encodings. */
3117 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003118
Barry Warsawfa701a81997-01-16 00:15:11 +00003119 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003120 return;
3121
Guido van Rossum43ff8681998-07-14 18:02:13 +00003122#if 0
3123 /* This was not a good idea; through <Destroy> bindings,
3124 Tcl_Finalize() may invoke Python code but at that point the
3125 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003126 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003127#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003128
Guido van Rossum18468821994-06-20 07:49:28 +00003129}