blob: e1238d691326f21ff833c9e040ba87044d54cfe0 [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
Guido van Rossumbf0dc9f1996-08-20 20:49:56 +000036#ifdef macintosh
37#define MAC_TCL
Guido van Rossum49b56061998-10-01 20:42:43 +000038#endif
39
Martin v. Löwis39195712003-01-04 00:33:13 +000040/* Allow using this code in Python 2.[12] */
41#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000042#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
45#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000046#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000047#endif
48
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000049#ifndef PyBool_Check
50#define PyBool_Check(o) 0
51#define PyBool_FromLong PyInt_FromLong
52#endif
53
Martin v. Löwis71e25a02002-10-01 18:08:06 +000054/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
55 making _tkinter correct for this API means to break earlier
56 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
57 earlier versions. Once Tcl releases before 8.4 don't need to be supported
58 anymore, this should go. */
59#define USE_COMPAT_CONST
60
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000061/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
62 it always; if Tcl is not threaded, the thread functions in
63 Tcl are empty. */
64#define TCL_THREADS
65
Jack Jansencb852442001-12-09 23:15:56 +000066#ifdef TK_FRAMEWORK
67#include <Tcl/tcl.h>
68#include <Tk/tk.h>
69#else
Guido van Rossum18468821994-06-20 07:49:28 +000070#include <tcl.h>
71#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000072#endif
Guido van Rossum18468821994-06-20 07:49:28 +000073
Jason Tishlerbbe89612002-12-31 20:30:46 +000074/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000075#ifndef CONST84_RETURN
76#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000077#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000078#define CONST
79#endif
80
Guido van Rossum3e819a71997-08-01 19:29:02 +000081#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
82
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000083#if TKMAJORMINOR < 8002
84#error "Tk older than 8.2 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000085#endif
86
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000087/* Unicode conversion assumes that Tcl_UniChar is two bytes.
88 We cannot test this directly, so we test UTF-8 size instead,
89 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000090 either UTF-16 or UCS-4.
91 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
92 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
93 as well.
94*/
95#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000096#error "unsupported Tcl configuration"
97#endif
98
Guido van Rossuma80649b2000-03-28 20:07:05 +000099#if defined(macintosh)
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000100/* Sigh, we have to include this to get at the tcl qd pointer */
101#include <tkMac.h>
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000102/* And this one we need to clear the menu bar */
103#include <Menus.h>
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000104#endif
105
Jack Jansen84c10b12001-07-16 19:32:52 +0000106#if !(defined(MS_WINDOWS) || defined(__CYGWIN__) || defined(macintosh))
107/* Mac has it, but it doesn't really work:-( */
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000108#define HAVE_CREATEFILEHANDLER
109#endif
110
Guido van Rossum00d93061998-05-28 23:06:38 +0000111#ifdef HAVE_CREATEFILEHANDLER
112
113/* Tcl_CreateFileHandler() changed several times; these macros deal with the
114 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
115 Unix, only because Jack added it back); when available on Windows, it only
116 applies to sockets. */
117
Guido van Rossum7bf15641998-05-22 18:28:17 +0000118#ifdef MS_WINDOWS
119#define FHANDLETYPE TCL_WIN_SOCKET
120#else
121#define FHANDLETYPE TCL_UNIX_FD
122#endif
123
Guido van Rossum00d93061998-05-28 23:06:38 +0000124/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
125 which uses this to handle Tcl events while the user is typing commands. */
126
127#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000128#define WAIT_FOR_STDIN
129#endif
130
Guido van Rossum00d93061998-05-28 23:06:38 +0000131#endif /* HAVE_CREATEFILEHANDLER */
132
Guido van Rossumad4db171998-06-13 13:56:28 +0000133#ifdef MS_WINDOWS
134#include <conio.h>
135#define WAIT_FOR_STDIN
136#endif
137
Guido van Rossum00d93061998-05-28 23:06:38 +0000138#ifdef WITH_THREAD
139
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000140/* The threading situation is complicated. Tcl is not thread-safe, except
141 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000142 So we need to use a lock around all uses of Tcl. Previously, the Python
143 interpreter lock was used for this. However, this causes problems when
144 other Python threads need to run while Tcl is blocked waiting for events.
145
146 To solve this problem, a separate lock for Tcl is introduced. Holding it
147 is incompatible with holding Python's interpreter lock. The following four
148 macros manipulate both locks together.
149
150 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
151 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
152 that could call an event handler, or otherwise affect the state of a Tcl
153 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000154 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000155 released and the lock for Tcl has been acquired.
156
Guido van Rossum5e977831998-06-15 14:03:52 +0000157 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
158 (For example, when transferring data from the Tcl interpreter result to a
159 Python string object.) This can be done by using different macros to close
160 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
161 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
162 releases the Tcl lock.
163
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000164 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000165 handlers when the handler needs to use Python. Such event handlers are
166 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000167 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000168 the Python interpreter lock, restoring the appropriate thread state, and
169 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
170 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000171 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000172
173 These locks expand to several statements and brackets; they should not be
174 used in branches of if statements and the like.
175
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000176 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
177 only valid in the thread that created it, and all Tk activity must happen in this
178 thread, also. That means that the mainloop must be invoked in the thread that
179 created the interpreter. Invoking commands from other threads is possible;
180 _tkinter will queue an event for the interpreter thread, which will then
181 execute the command and pass back the result. If the main thread is not in the
182 mainloop, and invoking commands causes an exception; if the main loop is running
183 but not processing events, the command invocation will block.
184
185 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
186 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
187 threads. So we use the Tcl TLS API.
188
Guido van Rossum00d93061998-05-28 23:06:38 +0000189*/
190
Guido van Rossum65d5b571998-12-21 19:32:43 +0000191static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000192
193#ifdef TCL_THREADS
194static Tcl_ThreadDataKey state_key;
195typedef PyThreadState *ThreadSpecificData;
196#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
197#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000198static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000199#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000200
201#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000202 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000203 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000204
205#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000206 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000207
Guido van Rossum62320c91998-06-15 04:36:09 +0000208#define ENTER_OVERLAP \
209 Py_END_ALLOW_THREADS
210
211#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000212 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000213
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000214#define ENTER_PYTHON \
215 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000216 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000217
218#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000219 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000220 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
221
222#define CHECK_TCL_APPARTMENT \
223 if (((TkappObject *)self)->threaded && \
224 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
225 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
226 return 0; \
227 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000228
229#else
230
231#define ENTER_TCL
232#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000233#define ENTER_OVERLAP
234#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000235#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000236#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000237#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000238
239#endif
240
Guido van Rossumec22c921996-02-25 04:50:29 +0000241#ifdef macintosh
242
243/*
244** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000245** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000246*/
247
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000248/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000249#define FREECAST (char *)
250
Guido van Rossumec22c921996-02-25 04:50:29 +0000251#include <Events.h> /* For EventRecord */
252
Fred Drake509d79a2000-07-08 04:04:38 +0000253typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
Guido van Rossum2834b972000-10-06 16:58:26 +0000254void Tcl_MacSetEventProc(TclMacConvertEventPtr procPtr);
255int TkMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000256
Jeremy Hylton938ace62002-07-17 16:30:39 +0000257static int PyMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000258
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000259#include <SIOUX.h>
260extern int SIOUXIsAppWindow(WindowPtr);
261
Guido van Rossumec22c921996-02-25 04:50:29 +0000262#endif /* macintosh */
263
Guido van Rossum97867b21996-08-08 19:09:53 +0000264#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000265#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000266#endif
267
Guido van Rossum18468821994-06-20 07:49:28 +0000268/**** Tkapp Object Declaration ****/
269
Jeremy Hylton938ace62002-07-17 16:30:39 +0000270static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000271
Guido van Rossum00d93061998-05-28 23:06:38 +0000272typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000273 PyObject_HEAD
274 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000275 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000276 int threaded; /* True if tcl_platform[threaded] */
277 Tcl_ThreadId thread_id;
278 int dispatching;
279 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000280 So we cache interesting types here. */
281 Tcl_ObjType *BooleanType;
282 Tcl_ObjType *ByteArrayType;
283 Tcl_ObjType *DoubleType;
284 Tcl_ObjType *IntType;
285 Tcl_ObjType *ListType;
286 Tcl_ObjType *ProcBodyType;
287 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000288} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000289
290#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000291#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000292#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000293
Guido van Rossum35d43371997-08-02 00:09:09 +0000294#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000295(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000296
Barry Warsawfa701a81997-01-16 00:15:11 +0000297
298
Guido van Rossum18468821994-06-20 07:49:28 +0000299/**** Error Handling ****/
300
301static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000302static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000303static int errorInCmd = 0;
304static PyObject *excInCmd;
305static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000306static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000307
Barry Warsawfa701a81997-01-16 00:15:11 +0000308
309
Guido van Rossum18468821994-06-20 07:49:28 +0000310static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000311Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000312{
Barry Warsawfa701a81997-01-16 00:15:11 +0000313 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
314 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000315}
316
Barry Warsawfa701a81997-01-16 00:15:11 +0000317
Barry Warsawfa701a81997-01-16 00:15:11 +0000318
Guido van Rossum18468821994-06-20 07:49:28 +0000319/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000320
321#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000322#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000323
Guido van Rossum00d93061998-05-28 23:06:38 +0000324/* Millisecond sleep() for Unix platforms. */
325
326static void
Fred Drake509d79a2000-07-08 04:04:38 +0000327Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000328{
329 /* XXX Too bad if you don't have select(). */
330 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000331 t.tv_sec = milli/1000;
332 t.tv_usec = (milli%1000) * 1000;
333 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
334}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000335#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000336
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000337/* Wait up to 1s for the mainloop to come up. */
338
339static int
340WaitForMainloop(TkappObject* self)
341{
342 int i;
343 for (i = 0; i < 10; i++) {
344 if (self->dispatching)
345 return 1;
346 Py_BEGIN_ALLOW_THREADS
347 Sleep(100);
348 Py_END_ALLOW_THREADS
349 }
350 if (self->dispatching)
351 return 1;
352 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
353 return 0;
354}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000355#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000356
Guido van Rossum00d93061998-05-28 23:06:38 +0000357
Guido van Rossum18468821994-06-20 07:49:28 +0000358static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000359AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000360{
Guido van Rossum35d43371997-08-02 00:09:09 +0000361 if (PyString_Check(value))
362 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000363#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000364 else if (PyUnicode_Check(value)) {
365 PyObject *v = PyUnicode_AsUTF8String(value);
366 if (v == NULL)
367 return NULL;
368 if (PyList_Append(tmp, v) != 0) {
369 Py_DECREF(v);
370 return NULL;
371 }
372 Py_DECREF(v);
373 return PyString_AsString(v);
374 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000375#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000376 else {
377 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000378 if (v == NULL)
379 return NULL;
380 if (PyList_Append(tmp, v) != 0) {
381 Py_DECREF(v);
382 return NULL;
383 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000384 Py_DECREF(v);
385 return PyString_AsString(v);
386 }
Guido van Rossum18468821994-06-20 07:49:28 +0000387}
388
Barry Warsawfa701a81997-01-16 00:15:11 +0000389
390
Guido van Rossum18468821994-06-20 07:49:28 +0000391#define ARGSZ 64
392
393static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000394Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000395{
Barry Warsawfa701a81997-01-16 00:15:11 +0000396 PyObject *tmp = NULL;
397 char *argvStore[ARGSZ];
398 char **argv = NULL;
399 int fvStore[ARGSZ];
400 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000401 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000402 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000403
Barry Warsawfa701a81997-01-16 00:15:11 +0000404 if (!(tmp = PyList_New(0)))
405 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000406
Barry Warsawfa701a81997-01-16 00:15:11 +0000407 argv = argvStore;
408 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000409
Barry Warsawfa701a81997-01-16 00:15:11 +0000410 if (args == NULL)
411 argc = 0;
412
413 else if (!PyTuple_Check(args)) {
414 argc = 1;
415 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000416 if (!(argv[0] = AsString(args, tmp)))
417 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000418 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000419 else {
420 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000421
Barry Warsawfa701a81997-01-16 00:15:11 +0000422 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000423 argv = (char **)ckalloc(argc * sizeof(char *));
424 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000425 if (argv == NULL || fv == NULL) {
426 PyErr_NoMemory();
427 goto finally;
428 }
429 }
430
431 for (i = 0; i < argc; i++) {
432 PyObject *v = PyTuple_GetItem(args, i);
433 if (PyTuple_Check(v)) {
434 fv[i] = 1;
435 if (!(argv[i] = Merge(v)))
436 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000437 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000438 }
439 else if (v == Py_None) {
440 argc = i;
441 break;
442 }
443 else {
444 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000445 if (!(argv[i] = AsString(v, tmp)))
446 goto finally;
447 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000448 }
449 }
Guido van Rossum18468821994-06-20 07:49:28 +0000450 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000451 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000452 if (res == NULL)
453 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000454
Barry Warsawfa701a81997-01-16 00:15:11 +0000455 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000456 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000457 if (fv[i]) {
458 ckfree(argv[i]);
459 }
460 if (argv != argvStore)
461 ckfree(FREECAST argv);
462 if (fv != fvStore)
463 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000464
Barry Warsawfa701a81997-01-16 00:15:11 +0000465 Py_DECREF(tmp);
466 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000467}
468
Barry Warsawfa701a81997-01-16 00:15:11 +0000469
470
Guido van Rossum18468821994-06-20 07:49:28 +0000471static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000472Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000473{
Barry Warsawfa701a81997-01-16 00:15:11 +0000474 int argc;
475 char **argv;
476 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000477
Barry Warsawfa701a81997-01-16 00:15:11 +0000478 if (list == NULL) {
479 Py_INCREF(Py_None);
480 return Py_None;
481 }
Guido van Rossum18468821994-06-20 07:49:28 +0000482
Guido van Rossum00d93061998-05-28 23:06:38 +0000483 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000484 /* Not a list.
485 * Could be a quoted string containing funnies, e.g. {"}.
486 * Return the string itself.
487 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000488 return PyString_FromString(list);
489 }
Guido van Rossum18468821994-06-20 07:49:28 +0000490
Barry Warsawfa701a81997-01-16 00:15:11 +0000491 if (argc == 0)
492 v = PyString_FromString("");
493 else if (argc == 1)
494 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000495 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000496 int i;
497 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000498
Barry Warsawfa701a81997-01-16 00:15:11 +0000499 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000500 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000501 Py_DECREF(v);
502 v = NULL;
503 break;
504 }
505 PyTuple_SetItem(v, i, w);
506 }
507 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000508 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000509 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000510}
511
Martin v. Löwisffad6332002-11-26 09:28:05 +0000512/* In some cases, Tcl will still return strings that are supposed to be
513 lists. SplitObj walks through a nested tuple, finding string objects that
514 need to be split. */
515
516PyObject *
517SplitObj(PyObject *arg)
518{
519 if (PyTuple_Check(arg)) {
520 int i, size;
521 PyObject *elem, *newelem, *result;
522
523 size = PyTuple_Size(arg);
524 result = NULL;
525 /* Recursively invoke SplitObj for all tuple items.
526 If this does not return a new object, no action is
527 needed. */
528 for(i = 0; i < size; i++) {
529 elem = PyTuple_GetItem(arg, i);
530 newelem = SplitObj(elem);
531 if (!newelem) {
532 Py_XDECREF(result);
533 return NULL;
534 }
535 if (!result) {
536 int k;
537 if (newelem == elem) {
538 Py_DECREF(newelem);
539 continue;
540 }
541 result = PyTuple_New(size);
542 if (!result)
543 return NULL;
544 for(k = 0; k < i; k++) {
545 elem = PyTuple_GetItem(arg, k);
546 Py_INCREF(elem);
547 PyTuple_SetItem(result, k, elem);
548 }
549 }
550 PyTuple_SetItem(result, i, newelem);
551 }
552 if (result)
553 return result;
554 /* Fall through, returning arg. */
555 }
556 else if (PyString_Check(arg)) {
557 int argc;
558 char **argv;
559 char *list = PyString_AsString(arg);
560
561 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
562 Py_INCREF(arg);
563 return arg;
564 }
565 Tcl_Free(FREECAST argv);
566 if (argc > 1)
567 return Split(PyString_AsString(arg));
568 /* Fall through, returning arg. */
569 }
570 Py_INCREF(arg);
571 return arg;
572}
Barry Warsawfa701a81997-01-16 00:15:11 +0000573
574
Guido van Rossum18468821994-06-20 07:49:28 +0000575/**** Tkapp Object ****/
576
577#ifndef WITH_APPINIT
578int
Fred Drake509d79a2000-07-08 04:04:38 +0000579Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000580{
Barry Warsawfa701a81997-01-16 00:15:11 +0000581 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000582
Barry Warsawfa701a81997-01-16 00:15:11 +0000583 main = Tk_MainWindow(interp);
584 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000585 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000586 return TCL_ERROR;
587 }
588 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000589 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000590 return TCL_ERROR;
591 }
592 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000593}
594#endif /* !WITH_APPINIT */
595
Guido van Rossum18468821994-06-20 07:49:28 +0000596
Barry Warsawfa701a81997-01-16 00:15:11 +0000597
598
599/* Initialize the Tk application; see the `main' function in
600 * `tkMain.c'.
601 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000602
Thomas Wouters58d05102000-07-24 14:43:35 +0000603static void EnableEventHook(void); /* Forward */
604static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000605
Barry Warsawfa701a81997-01-16 00:15:11 +0000606static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000607Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000608 int interactive, int wantobjects)
Barry Warsawfa701a81997-01-16 00:15:11 +0000609{
610 TkappObject *v;
611 char *argv0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000612
Guido van Rossumb18618d2000-05-03 23:44:39 +0000613 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000614 if (v == NULL)
615 return NULL;
616
617 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000618 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000619 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
620 TCL_GLOBAL_ONLY) != NULL;
621 v->thread_id = Tcl_GetCurrentThread();
622 v->dispatching = 0;
623
624#ifndef TCL_THREADS
625 if (v->threaded) {
626 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
627 Py_DECREF(v);
628 return 0;
629 }
630#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000631#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000632 if (v->threaded && tcl_lock) {
633 /* If Tcl is threaded, we don't need the lock. */
634 PyThread_free_lock(tcl_lock);
635 tcl_lock = NULL;
636 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000637#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000638
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000639 v->BooleanType = Tcl_GetObjType("boolean");
640 v->ByteArrayType = Tcl_GetObjType("bytearray");
641 v->DoubleType = Tcl_GetObjType("double");
642 v->IntType = Tcl_GetObjType("int");
643 v->ListType = Tcl_GetObjType("list");
644 v->ProcBodyType = Tcl_GetObjType("procbody");
645 v->StringType = Tcl_GetObjType("string");
646
Guido van Rossuma80649b2000-03-28 20:07:05 +0000647#if defined(macintosh)
648 /* This seems to be needed */
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000649 ClearMenuBar();
650 TkMacInitMenus(v->interp);
651#endif
Jack Jansencb852442001-12-09 23:15:56 +0000652
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000653 /* Delete the 'exit' command, which can screw things up */
654 Tcl_DeleteCommand(v->interp, "exit");
655
Barry Warsawfa701a81997-01-16 00:15:11 +0000656 if (screenName != NULL)
657 Tcl_SetVar2(v->interp, "env", "DISPLAY",
658 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000659
Barry Warsawfa701a81997-01-16 00:15:11 +0000660 if (interactive)
661 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
662 else
663 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000664
Barry Warsawfa701a81997-01-16 00:15:11 +0000665 /* This is used to get the application class for Tk 4.1 and up */
666 argv0 = (char*)ckalloc(strlen(className) + 1);
667 if (!argv0) {
668 PyErr_NoMemory();
669 Py_DECREF(v);
670 return NULL;
671 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000672
Barry Warsawfa701a81997-01-16 00:15:11 +0000673 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000674 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000675 argv0[0] = tolower(argv0[0]);
676 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
677 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000678
Barry Warsawfa701a81997-01-16 00:15:11 +0000679 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000680 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000681
Guido van Rossum7bf15641998-05-22 18:28:17 +0000682 EnableEventHook();
683
Barry Warsawfa701a81997-01-16 00:15:11 +0000684 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000685}
686
Barry Warsawfa701a81997-01-16 00:15:11 +0000687
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000688static void
689Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
690 Tcl_Condition *cond, Tcl_Mutex *mutex)
691{
692 Py_BEGIN_ALLOW_THREADS;
693 Tcl_MutexLock(mutex);
694 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
695 Tcl_ThreadAlert(self->thread_id);
696 Tcl_ConditionWait(cond, mutex, NULL);
697 Tcl_MutexUnlock(mutex);
698 Py_END_ALLOW_THREADS
699}
700
Barry Warsawfa701a81997-01-16 00:15:11 +0000701
Guido van Rossum18468821994-06-20 07:49:28 +0000702/** Tcl Eval **/
703
Martin v. Löwisffad6332002-11-26 09:28:05 +0000704typedef struct {
705 PyObject_HEAD
706 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000707 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000708} PyTclObject;
709
710staticforward PyTypeObject PyTclObject_Type;
711#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
712
713static PyObject *
714newPyTclObject(Tcl_Obj *arg)
715{
716 PyTclObject *self;
717 self = PyObject_New(PyTclObject, &PyTclObject_Type);
718 if (self == NULL)
719 return NULL;
720 Tcl_IncrRefCount(arg);
721 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000722 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000723 return (PyObject*)self;
724}
725
726static void
727PyTclObject_dealloc(PyTclObject *self)
728{
729 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000730 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000731 PyObject_Del(self);
732}
733
734static PyObject *
735PyTclObject_str(PyTclObject *self)
736{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000737 if (self->string && PyString_Check(self->string)) {
738 Py_INCREF(self->string);
739 return self->string;
740 }
741 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000742 return PyString_FromString(Tcl_GetString(self->value));
743}
744
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000745static char*
746PyTclObject_TclString(PyObject *self)
747{
748 return Tcl_GetString(((PyTclObject*)self)->value);
749}
750
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000751/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000752PyDoc_STRVAR(PyTclObject_string__doc__,
753"the string representation of this object, either as string or Unicode");
754
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000755static PyObject *
756PyTclObject_string(PyTclObject *self, void *ignored)
757{
758 char *s;
759 int i, len;
760 if (!self->string) {
761 s = Tcl_GetStringFromObj(self->value, &len);
762 for (i = 0; i < len; i++)
763 if (s[i] & 0x80)
764 break;
765#ifdef Py_USING_UNICODE
766 if (i == len)
767 /* It is an ASCII string. */
768 self->string = PyString_FromStringAndSize(s, len);
769 else {
770 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
771 if (!self->string) {
772 PyErr_Clear();
773 self->string = PyString_FromStringAndSize(s, len);
774 }
775 }
776#else
777 self->string = PyString_FromStringAndSize(s, len);
778#endif
779 if (!self->string)
780 return NULL;
781 }
782 Py_INCREF(self->string);
783 return self->string;
784}
785
786#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000787PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
788
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000789static PyObject *
790PyTclObject_unicode(PyTclObject *self, void *ignored)
791{
792 char *s;
793 int len;
794 if (self->string && PyUnicode_Check(self->string)) {
795 Py_INCREF(self->string);
796 return self->string;
797 }
798 /* XXX Could chache result if it is non-ASCII. */
799 s = Tcl_GetStringFromObj(self->value, &len);
800 return PyUnicode_DecodeUTF8(s, len, "strict");
801}
802#endif
803
Martin v. Löwisffad6332002-11-26 09:28:05 +0000804static PyObject *
805PyTclObject_repr(PyTclObject *self)
806{
807 char buf[50];
808 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
809 self->value->typePtr->name, (int)self->value);
810 return PyString_FromString(buf);
811}
812
Martin v. Löwis39195712003-01-04 00:33:13 +0000813PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
814
Martin v. Löwisffad6332002-11-26 09:28:05 +0000815static PyObject*
816get_typename(PyTclObject* obj, void* ignored)
817{
818 return PyString_FromString(obj->value->typePtr->name);
819}
820
Martin v. Löwis39195712003-01-04 00:33:13 +0000821
Martin v. Löwisffad6332002-11-26 09:28:05 +0000822static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000823 {"typename", (getter)get_typename, NULL, get_typename__doc__},
824 {"string", (getter)PyTclObject_string, NULL,
825 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000826 {0},
827};
828
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000829static PyMethodDef PyTclObject_methods[] = {
830 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000831 PyTclObject_unicode__doc__},
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000832 {0}
833};
834
Martin v. Löwisffad6332002-11-26 09:28:05 +0000835statichere PyTypeObject PyTclObject_Type = {
836 PyObject_HEAD_INIT(NULL)
837 0, /*ob_size*/
838 "_tkinter.Tcl_Obj", /*tp_name*/
839 sizeof(PyTclObject), /*tp_basicsize*/
840 0, /*tp_itemsize*/
841 /* methods */
842 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
843 0, /*tp_print*/
844 0, /*tp_getattr*/
845 0, /*tp_setattr*/
846 0, /*tp_compare*/
847 (reprfunc)PyTclObject_repr, /*tp_repr*/
848 0, /*tp_as_number*/
849 0, /*tp_as_sequence*/
850 0, /*tp_as_mapping*/
851 0, /*tp_hash*/
852 0, /*tp_call*/
853 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000854 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000855 0, /*tp_setattro*/
856 0, /*tp_as_buffer*/
857 Py_TPFLAGS_DEFAULT, /*tp_flags*/
858 0, /*tp_doc*/
859 0, /*tp_traverse*/
860 0, /*tp_clear*/
861 0, /*tp_richcompare*/
862 0, /*tp_weaklistoffset*/
863 0, /*tp_iter*/
864 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000865 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000866 0, /*tp_members*/
867 PyTclObject_getsetlist, /*tp_getset*/
868 0, /*tp_base*/
869 0, /*tp_dict*/
870 0, /*tp_descr_get*/
871 0, /*tp_descr_set*/
872 0, /*tp_dictoffset*/
873 0, /*tp_init*/
874 0, /*tp_alloc*/
875 0, /*tp_new*/
876 0, /*tp_free*/
877 0, /*tp_is_gc*/
878};
879
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000880static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000881AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000882{
883 Tcl_Obj *result;
884
885 if (PyString_Check(value))
886 return Tcl_NewStringObj(PyString_AS_STRING(value),
887 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000888 else if (PyBool_Check(value))
889 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000890 else if (PyInt_Check(value))
891 return Tcl_NewLongObj(PyInt_AS_LONG(value));
892 else if (PyFloat_Check(value))
893 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
894 else if (PyTuple_Check(value)) {
895 Tcl_Obj **argv = (Tcl_Obj**)
896 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
897 int i;
898 if(!argv)
899 return 0;
900 for(i=0;i<PyTuple_Size(value);i++)
901 argv[i] = AsObj(PyTuple_GetItem(value,i));
902 result = Tcl_NewListObj(PyTuple_Size(value), argv);
903 ckfree(FREECAST argv);
904 return result;
905 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000906#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000907 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000908 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
909 int size = PyUnicode_GET_SIZE(value);
910 /* This #ifdef assumes that Tcl uses UCS-2.
911 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000912#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000913 Tcl_UniChar *outbuf;
914 int i;
915 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
916 if (!outbuf) {
917 PyErr_NoMemory();
918 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000919 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000920 for (i = 0; i < size; i++) {
921 if (inbuf[i] >= 0x10000) {
922 /* Tcl doesn't do UTF-16, yet. */
923 PyErr_SetString(PyExc_ValueError,
924 "unsupported character");
925 ckfree(FREECAST outbuf);
926 return NULL;
927 }
928 outbuf[i] = inbuf[i];
929 }
930 result = Tcl_NewUnicodeObj(outbuf, size);
931 ckfree(FREECAST outbuf);
932 return result;
933#else
934 return Tcl_NewUnicodeObj(inbuf, size);
935#endif
936
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000937 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000938#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000939 else if(PyTclObject_Check(value)) {
940 Tcl_Obj *v = ((PyTclObject*)value)->value;
941 Tcl_IncrRefCount(v);
942 return v;
943 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000944 else {
945 PyObject *v = PyObject_Str(value);
946 if (!v)
947 return 0;
948 result = AsObj(v);
949 Py_DECREF(v);
950 return result;
951 }
952}
953
Martin v. Löwisffad6332002-11-26 09:28:05 +0000954static PyObject*
955FromObj(PyObject* tkapp, Tcl_Obj *value)
956{
957 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000958 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000959
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000960 if (value->typePtr == NULL) {
961 /* If the result contains any bytes with the top bit set,
962 it's UTF-8 and we should decode it to Unicode */
963#ifdef Py_USING_UNICODE
964 int i;
965 char *s = value->bytes;
966 int len = value->length;
967 for (i = 0; i < len; i++) {
968 if (value->bytes[i] & 0x80)
969 break;
970 }
971
972 if (i == value->length)
973 result = PyString_FromStringAndSize(s, len);
974 else {
975 /* Convert UTF-8 to Unicode string */
976 result = PyUnicode_DecodeUTF8(s, len, "strict");
977 if (result == NULL) {
978 PyErr_Clear();
979 result = PyString_FromStringAndSize(s, len);
980 }
981 }
982#else
983 res = PyString_FromStringAndSize(value->bytes, value->length);
984#endif
985 return result;
986 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000987
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000988 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000989 result = value->internalRep.longValue ? Py_True : Py_False;
990 Py_INCREF(result);
991 return result;
992 }
993
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000994 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000995 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000996 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000997 return PyString_FromStringAndSize(data, size);
998 }
999
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001000 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001001 return PyFloat_FromDouble(value->internalRep.doubleValue);
1002 }
1003
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001004 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001005 return PyInt_FromLong(value->internalRep.longValue);
1006 }
1007
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001008 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001009 int size;
1010 int i, status;
1011 PyObject *elem;
1012 Tcl_Obj *tcl_elem;
1013
1014 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1015 if (status == TCL_ERROR)
1016 return Tkinter_Error(tkapp);
1017 result = PyTuple_New(size);
1018 if (!result)
1019 return NULL;
1020 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001021 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001022 value, i, &tcl_elem);
1023 if (status == TCL_ERROR) {
1024 Py_DECREF(result);
1025 return Tkinter_Error(tkapp);
1026 }
1027 elem = FromObj(tkapp, tcl_elem);
1028 if (!elem) {
1029 Py_DECREF(result);
1030 return NULL;
1031 }
1032 PyTuple_SetItem(result, i, elem);
1033 }
1034 return result;
1035 }
1036
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001037 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001038 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001039 }
1040
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001041 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001042#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001043#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001044 PyObject *result;
1045 int size;
1046 Tcl_UniChar *input;
1047 Py_UNICODE *output;
1048
1049 size = Tcl_GetCharLength(value);
1050 result = PyUnicode_FromUnicode(NULL, size);
1051 if (!result)
1052 return NULL;
1053 input = Tcl_GetUnicode(value);
1054 output = PyUnicode_AS_UNICODE(result);
1055 while (size--)
1056 *output++ = *input++;
1057 return result;
1058#else
1059 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1060 Tcl_GetCharLength(value));
1061#endif
1062#else
1063 int size;
1064 char *c;
1065 c = Tcl_GetStringFromObj(value, &size);
1066 return PyString_FromStringAndSize(c, size);
1067#endif
1068 }
1069
1070 return newPyTclObject(value);
1071}
1072
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001073/* This mutex synchronizes inter-thread command calls. */
1074
1075TCL_DECLARE_MUTEX(call_mutex)
1076
1077typedef struct Tkapp_CallEvent {
1078 Tcl_Event ev; /* Must be first */
1079 TkappObject *self;
1080 PyObject *args;
1081 int flags;
1082 PyObject **res;
1083 PyObject **exc_type, **exc_value, **exc_tb;
1084 Tcl_Condition done;
1085} Tkapp_CallEvent;
1086
1087void
1088Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001089{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001090 int i;
1091 for (i = 0; i < objc; i++)
1092 Tcl_DecrRefCount(objv[i]);
1093 if (objv != objStore)
1094 ckfree(FREECAST objv);
1095}
Guido van Rossum18468821994-06-20 07:49:28 +00001096
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001097/* Convert Python objects to Tcl objects. This must happen in the
1098 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001099
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001100static Tcl_Obj**
1101Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1102{
1103 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001104 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001105 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001106 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001107
Guido van Rossum212643f1998-04-29 16:22:14 +00001108 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001109 objv[0] = AsObj(args);
1110 if (objv[0] == 0)
1111 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001112 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001113 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001114 }
1115 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001116 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001117
Guido van Rossum632de272000-03-29 00:19:50 +00001118 if (objc > ARGSZ) {
1119 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1120 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001121 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001122 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001123 goto finally;
1124 }
1125 }
1126
Guido van Rossum632de272000-03-29 00:19:50 +00001127 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001128 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001129 if (v == Py_None) {
1130 objc = i;
1131 break;
1132 }
Guido van Rossum632de272000-03-29 00:19:50 +00001133 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001134 if (!objv[i]) {
1135 /* Reset objc, so it attempts to clear
1136 objects only up to i. */
1137 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001138 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001139 }
Guido van Rossum632de272000-03-29 00:19:50 +00001140 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001141 }
1142 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001143 *pobjc = objc;
1144 return objv;
1145finally:
1146 Tkapp_CallDeallocArgs(objv, objStore, objc);
1147 return NULL;
1148}
Guido van Rossum212643f1998-04-29 16:22:14 +00001149
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001150/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001151
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001152static PyObject*
1153Tkapp_CallResult(TkappObject *self)
1154{
1155 PyObject *res = NULL;
1156 if(self->wantobjects) {
1157 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001158 /* Not sure whether the IncrRef is necessary, but something
1159 may overwrite the interpreter result while we are
1160 converting it. */
1161 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001162 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001163 Tcl_DecrRefCount(value);
1164 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001165 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001166 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001167
Guido van Rossum990f5c62000-05-04 15:07:16 +00001168 /* If the result contains any bytes with the top bit set,
1169 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001170#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001171 while (*p != '\0') {
1172 if (*p & 0x80)
1173 break;
1174 p++;
1175 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001176
Guido van Rossum990f5c62000-05-04 15:07:16 +00001177 if (*p == '\0')
1178 res = PyString_FromStringAndSize(s, (int)(p-s));
1179 else {
1180 /* Convert UTF-8 to Unicode string */
1181 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001182 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1183 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001184 PyErr_Clear();
1185 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001186 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001187 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001188#else
1189 p = strchr(p, '\0');
1190 res = PyString_FromStringAndSize(s, (int)(p-s));
1191#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001192 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001193 return res;
1194}
Guido van Rossum632de272000-03-29 00:19:50 +00001195
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001196/* Tkapp_CallProc is the event procedure that is executed in the context of
1197 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1198 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001199
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001200static int
1201Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1202{
1203 Tcl_Obj *objStore[ARGSZ];
1204 Tcl_Obj **objv;
1205 int objc;
1206 int i;
1207 ENTER_PYTHON
1208 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1209 if (!objv) {
1210 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1211 *(e->res) = NULL;
1212 }
1213 LEAVE_PYTHON
1214 if (!objv)
1215 goto done;
1216 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1217 ENTER_PYTHON
1218 if (i == TCL_ERROR) {
1219 *(e->res) = NULL;
1220 *(e->exc_type) = NULL;
1221 *(e->exc_tb) = NULL;
1222 *(e->exc_value) = PyObject_CallFunction(
1223 Tkinter_TclError, "s",
1224 Tcl_GetStringResult(e->self->interp));
1225 }
1226 else {
1227 *(e->res) = Tkapp_CallResult(e->self);
1228 }
1229 LEAVE_PYTHON
1230 done:
1231 /* Wake up calling thread. */
1232 Tcl_MutexLock(&call_mutex);
1233 Tcl_ConditionNotify(&e->done);
1234 Tcl_MutexUnlock(&call_mutex);
1235 return 1;
1236}
1237
1238/* This is the main entry point for calling a Tcl command.
1239 It supports three cases, with regard to threading:
1240 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1241 the context of the calling thread.
1242 2. Tcl is threaded, caller of the command is in the interpreter thread:
1243 Execute the command in the calling thread. Since the Tcl lock will
1244 not be used, we can merge that with case 1.
1245 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1246 the interpreter thread. Allocation of Tcl objects needs to occur in the
1247 interpreter thread, so we ship the PyObject* args to the target thread,
1248 and perform processing there. */
1249
1250static PyObject *
1251Tkapp_Call(PyObject *_self, PyObject *args)
1252{
1253 Tcl_Obj *objStore[ARGSZ];
1254 Tcl_Obj **objv = NULL;
1255 int objc, i;
1256 PyObject *res = NULL;
1257 TkappObject *self = (TkappObject*)_self;
1258 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1259 int flags = TCL_EVAL_DIRECT;
1260
Martin v. Löwisa9656492003-03-30 08:44:58 +00001261#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001262 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1263 /* We cannot call the command directly. Instead, we must
1264 marshal the parameters to the interpreter thread. */
1265 Tkapp_CallEvent *ev;
1266 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001267 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001268 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001269 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1270 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1271 ev->self = self;
1272 ev->args = args;
1273 ev->res = &res;
1274 ev->exc_type = &exc_type;
1275 ev->exc_value = &exc_value;
1276 ev->exc_tb = &exc_tb;
1277 ev->done = (Tcl_Condition)0;
1278
1279 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1280
1281 if (res == NULL) {
1282 if (exc_type)
1283 PyErr_Restore(exc_type, exc_value, exc_tb);
1284 else
1285 PyErr_SetObject(Tkinter_TclError, exc_value);
1286 }
1287 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001288 else
1289#endif
1290 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001291
1292 objv = Tkapp_CallArgs(args, objStore, &objc);
1293 if (!objv)
1294 return NULL;
1295
1296 ENTER_TCL
1297
1298 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1299
1300 ENTER_OVERLAP
1301
1302 if (i == TCL_ERROR)
1303 Tkinter_Error(_self);
1304 else
1305 res = Tkapp_CallResult(self);
1306
1307 LEAVE_OVERLAP_TCL
1308
1309 Tkapp_CallDeallocArgs(objv, objStore, objc);
1310 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001311 return res;
1312}
1313
1314
1315static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001316Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001317{
Guido van Rossum212643f1998-04-29 16:22:14 +00001318 /* Could do the same here as for Tkapp_Call(), but this is not used
1319 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1320 way for the user to do what all its Global* variants do (save and
1321 reset the scope pointer, call the local version, restore the saved
1322 scope pointer). */
1323
Guido van Rossum62320c91998-06-15 04:36:09 +00001324 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001325 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001326
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001327 CHECK_TCL_APPARTMENT;
1328
Guido van Rossum62320c91998-06-15 04:36:09 +00001329 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001330 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001331 int err;
1332 ENTER_TCL
1333 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001334 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001335 if (err == TCL_ERROR)
1336 res = Tkinter_Error(self);
1337 else
1338 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001339 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001340 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001341 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001342
1343 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001344}
1345
1346static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001347Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001348{
Barry Warsawfa701a81997-01-16 00:15:11 +00001349 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001350 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001351 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001352
Guido van Rossum43713e52000-02-29 13:59:29 +00001353 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001354 return NULL;
1355
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001356 CHECK_TCL_APPARTMENT;
1357
Guido van Rossum00d93061998-05-28 23:06:38 +00001358 ENTER_TCL
1359 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001360 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001361 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001362 res = Tkinter_Error(self);
1363 else
1364 res = PyString_FromString(Tkapp_Result(self));
1365 LEAVE_OVERLAP_TCL
1366 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001367}
1368
1369static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001370Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001371{
Barry Warsawfa701a81997-01-16 00:15:11 +00001372 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001373 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001374 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001375
Guido van Rossum43713e52000-02-29 13:59:29 +00001376 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001377 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001378
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001379 CHECK_TCL_APPARTMENT;
1380
Guido van Rossum00d93061998-05-28 23:06:38 +00001381 ENTER_TCL
1382 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001383 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001384 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001385 res = Tkinter_Error(self);
1386 else
1387 res = PyString_FromString(Tkapp_Result(self));
1388 LEAVE_OVERLAP_TCL
1389 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001390}
1391
1392static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001393Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001394{
Barry Warsawfa701a81997-01-16 00:15:11 +00001395 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001396 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001397 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001398
Guido van Rossum43713e52000-02-29 13:59:29 +00001399 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001400 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001401
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001402 CHECK_TCL_APPARTMENT;
1403
Guido van Rossum00d93061998-05-28 23:06:38 +00001404 ENTER_TCL
1405 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001406 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001407 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001408 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001409
Guido van Rossum62320c91998-06-15 04:36:09 +00001410 else
1411 res = PyString_FromString(Tkapp_Result(self));
1412 LEAVE_OVERLAP_TCL
1413 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001414}
1415
1416static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001417Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001418{
Barry Warsawfa701a81997-01-16 00:15:11 +00001419 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001420 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001421 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001422
Guido van Rossum35d43371997-08-02 00:09:09 +00001423 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001424 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001425
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001426 CHECK_TCL_APPARTMENT;
1427
Guido van Rossum00d93061998-05-28 23:06:38 +00001428 ENTER_TCL
1429 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001430 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001431 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001432 res = Tkinter_Error(self);
1433 else
1434 res = PyString_FromString(Tkapp_Result(self));
1435 LEAVE_OVERLAP_TCL
1436 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001437}
1438
1439static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001440Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001441{
Barry Warsawfa701a81997-01-16 00:15:11 +00001442 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001443
Guido van Rossum43713e52000-02-29 13:59:29 +00001444 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001445 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001446 CHECK_TCL_APPARTMENT;
1447
Guido van Rossum00d93061998-05-28 23:06:38 +00001448 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001449 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001450 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001451
Barry Warsawfa701a81997-01-16 00:15:11 +00001452 Py_INCREF(Py_None);
1453 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001454}
1455
Barry Warsawfa701a81997-01-16 00:15:11 +00001456
1457
Guido van Rossum18468821994-06-20 07:49:28 +00001458/** Tcl Variable **/
1459
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001460TCL_DECLARE_MUTEX(var_mutex)
1461
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001462typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001463typedef struct VarEvent {
1464 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001465 PyObject *self;
1466 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001467 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001468 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001469 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001470 PyObject **exc_type;
1471 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001472 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001473} VarEvent;
1474
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001475static int
1476varname_converter(PyObject *in, void *_out)
1477{
1478 char **out = (char**)_out;
1479 if (PyString_Check(in)) {
1480 *out = PyString_AsString(in);
1481 return 1;
1482 }
1483 if (PyTclObject_Check(in)) {
1484 *out = PyTclObject_TclString(in);
1485 return 1;
1486 }
1487 /* XXX: Should give diagnostics. */
1488 return 0;
1489}
1490
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001491void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001492var_perform(VarEvent *ev)
1493{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001494 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1495 if (!*(ev->res)) {
1496 PyObject *exc, *val, *tb;
1497 PyErr_Fetch(&exc, &val, &tb);
1498 PyErr_NormalizeException(&exc, &val, &tb);
1499 *(ev->exc_type) = exc;
1500 *(ev->exc_val) = val;
1501 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001502 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001503
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001504}
1505
1506static int
1507var_proc(VarEvent* ev, int flags)
1508{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001509 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001510 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001511 Tcl_MutexLock(&var_mutex);
1512 Tcl_ConditionNotify(&ev->cond);
1513 Tcl_MutexUnlock(&var_mutex);
1514 LEAVE_PYTHON
1515 return 1;
1516}
1517
1518static PyObject*
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001519var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001520{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001521 TkappObject *self = (TkappObject*)_self;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001522#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001523 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001524 TkappObject *self = (TkappObject*)_self;
1525 VarEvent *ev;
1526 PyObject *res, *exc_type, *exc_val;
1527
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001528 /* The current thread is not the interpreter thread. Marshal
1529 the call to the interpreter thread, then wait for
1530 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001531 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001532 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001533
1534 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1535
1536 ev->self = _self;
1537 ev->args = args;
1538 ev->flags = flags;
1539 ev->func = func;
1540 ev->res = &res;
1541 ev->exc_type = &exc_type;
1542 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001543 ev->cond = NULL;
1544 ev->ev.proc = (Tcl_EventProc*)var_proc;
1545 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001546 if (!res) {
1547 PyErr_SetObject(exc_type, exc_val);
1548 Py_DECREF(exc_type);
1549 Py_DECREF(exc_val);
1550 return NULL;
1551 }
1552 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001553 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001554#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001555 /* Tcl is not threaded, or this is the interpreter thread. */
1556 return func(_self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001557}
1558
Guido van Rossum18468821994-06-20 07:49:28 +00001559static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001560SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001561{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001562 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001563 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001564 PyObject *res = NULL;
1565 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001566
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001567 if (PyArg_ParseTuple(args, "O&O:setvar",
1568 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001569 /* XXX Acquire tcl lock??? */
1570 newval = AsObj(newValue);
1571 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001572 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001573 ENTER_TCL
1574 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1575 newval, flags);
1576 ENTER_OVERLAP
1577 if (!ok)
1578 Tkinter_Error(self);
1579 else {
1580 res = Py_None;
1581 Py_INCREF(res);
1582 }
1583 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001584 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001585 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001586 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001587 if (PyArg_ParseTuple(args, "ssO:setvar",
1588 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001589 /* XXX must hold tcl lock already??? */
1590 newval = AsObj(newValue);
1591 ENTER_TCL
1592 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1593 ENTER_OVERLAP
1594 if (!ok)
1595 Tkinter_Error(self);
1596 else {
1597 res = Py_None;
1598 Py_INCREF(res);
1599 }
1600 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001601 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001602 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001603 return NULL;
1604 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001605 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001606 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001607}
1608
1609static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001610Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001611{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001612 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001613}
1614
1615static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001616Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001617{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001618 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001619}
1620
Barry Warsawfa701a81997-01-16 00:15:11 +00001621
1622
Guido van Rossum18468821994-06-20 07:49:28 +00001623static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001624GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001625{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001626 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001627 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001628 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001629
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001630 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1631 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001632 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001633
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001634 ENTER_TCL
1635 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1636 ENTER_OVERLAP
1637 res = FromObj(self, tres);
1638 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001639 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001640}
1641
1642static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001643Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001644{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001645 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001646}
1647
1648static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001649Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001650{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001651 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001652}
1653
Barry Warsawfa701a81997-01-16 00:15:11 +00001654
1655
Guido van Rossum18468821994-06-20 07:49:28 +00001656static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001657UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001658{
Guido van Rossum35d43371997-08-02 00:09:09 +00001659 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001660 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001661 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001662
Guido van Rossum43713e52000-02-29 13:59:29 +00001663 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001664 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001665
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001666 ENTER_TCL
1667 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1668 ENTER_OVERLAP
1669 if (code == TCL_ERROR)
1670 res = Tkinter_Error(self);
1671 else {
1672 Py_INCREF(Py_None);
1673 res = Py_None;
1674 }
1675 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001676 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001677}
1678
1679static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001680Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001681{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001682 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001683}
1684
1685static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001686Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001687{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001688 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001689}
1690
Barry Warsawfa701a81997-01-16 00:15:11 +00001691
1692
Guido van Rossum18468821994-06-20 07:49:28 +00001693/** Tcl to Python **/
1694
1695static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001696Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001697{
Barry Warsawfa701a81997-01-16 00:15:11 +00001698 char *s;
1699 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001700
Martin v. Löwisffad6332002-11-26 09:28:05 +00001701 if (PyTuple_Size(args) == 1) {
1702 PyObject* o = PyTuple_GetItem(args, 0);
1703 if (PyInt_Check(o)) {
1704 Py_INCREF(o);
1705 return o;
1706 }
1707 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001708 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001709 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001710 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001711 return Tkinter_Error(self);
1712 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001713}
1714
1715static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001716Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001717{
Barry Warsawfa701a81997-01-16 00:15:11 +00001718 char *s;
1719 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001720
Martin v. Löwisffad6332002-11-26 09:28:05 +00001721 if (PyTuple_Size(args) == 1) {
1722 PyObject *o = PyTuple_GetItem(args, 0);
1723 if (PyFloat_Check(o)) {
1724 Py_INCREF(o);
1725 return o;
1726 }
1727 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001728 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001729 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001730 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001731 return Tkinter_Error(self);
1732 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001733}
1734
1735static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001736Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001737{
Barry Warsawfa701a81997-01-16 00:15:11 +00001738 char *s;
1739 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001740
Martin v. Löwisffad6332002-11-26 09:28:05 +00001741 if (PyTuple_Size(args) == 1) {
1742 PyObject *o = PyTuple_GetItem(args, 0);
1743 if (PyInt_Check(o)) {
1744 Py_INCREF(o);
1745 return o;
1746 }
1747 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001748 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001749 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001750 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1751 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001752 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001753}
1754
1755static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001756Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001757{
Barry Warsawfa701a81997-01-16 00:15:11 +00001758 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001759 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001760 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001761
Guido van Rossum43713e52000-02-29 13:59:29 +00001762 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001763 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001764
1765 CHECK_TCL_APPARTMENT;
1766
Guido van Rossum00d93061998-05-28 23:06:38 +00001767 ENTER_TCL
1768 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001769 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001770 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001771 res = Tkinter_Error(self);
1772 else
1773 res = Py_BuildValue("s", Tkapp_Result(self));
1774 LEAVE_OVERLAP_TCL
1775 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001776}
1777
1778static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001779Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001780{
Barry Warsawfa701a81997-01-16 00:15:11 +00001781 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001782 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001783 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001784 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001785
Guido van Rossum43713e52000-02-29 13:59:29 +00001786 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001787 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001788
1789 CHECK_TCL_APPARTMENT;
1790
Guido van Rossum00d93061998-05-28 23:06:38 +00001791 ENTER_TCL
1792 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001793 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001794 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001795 res = Tkinter_Error(self);
1796 else
1797 res = Py_BuildValue("l", v);
1798 LEAVE_OVERLAP_TCL
1799 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001800}
1801
1802static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001803Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001804{
Barry Warsawfa701a81997-01-16 00:15:11 +00001805 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001806 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001807 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001808 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001809
Guido van Rossum43713e52000-02-29 13:59:29 +00001810 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001811 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001812 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001813 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001814 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001815 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001816 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001817 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001818 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001819 res = Tkinter_Error(self);
1820 else
1821 res = Py_BuildValue("d", v);
1822 LEAVE_OVERLAP_TCL
1823 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001824}
1825
1826static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001827Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001828{
Barry Warsawfa701a81997-01-16 00:15:11 +00001829 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001830 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001831 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001832 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001833
Guido van Rossum43713e52000-02-29 13:59:29 +00001834 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001835 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001836 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001837 ENTER_TCL
1838 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001839 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001840 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001841 res = Tkinter_Error(self);
1842 else
1843 res = Py_BuildValue("i", v);
1844 LEAVE_OVERLAP_TCL
1845 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001846}
1847
Barry Warsawfa701a81997-01-16 00:15:11 +00001848
1849
Guido van Rossum18468821994-06-20 07:49:28 +00001850static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001851Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001852{
Barry Warsawfa701a81997-01-16 00:15:11 +00001853 char *list;
1854 int argc;
1855 char **argv;
1856 PyObject *v;
1857 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001858
Martin v. Löwisffad6332002-11-26 09:28:05 +00001859 if (PyTuple_Size(args) == 1) {
1860 v = PyTuple_GetItem(args, 0);
1861 if (PyTuple_Check(v)) {
1862 Py_INCREF(v);
1863 return v;
1864 }
1865 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001866 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001867 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001868
Barry Warsawfa701a81997-01-16 00:15:11 +00001869 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1870 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001871
Barry Warsawfa701a81997-01-16 00:15:11 +00001872 if (!(v = PyTuple_New(argc)))
1873 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001874
Barry Warsawfa701a81997-01-16 00:15:11 +00001875 for (i = 0; i < argc; i++) {
1876 PyObject *s = PyString_FromString(argv[i]);
1877 if (!s || PyTuple_SetItem(v, i, s)) {
1878 Py_DECREF(v);
1879 v = NULL;
1880 goto finally;
1881 }
1882 }
Guido van Rossum18468821994-06-20 07:49:28 +00001883
Barry Warsawfa701a81997-01-16 00:15:11 +00001884 finally:
1885 ckfree(FREECAST argv);
1886 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001887}
1888
1889static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001890Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001891{
Barry Warsawfa701a81997-01-16 00:15:11 +00001892 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001893
Martin v. Löwisffad6332002-11-26 09:28:05 +00001894 if (PyTuple_Size(args) == 1) {
1895 PyObject* o = PyTuple_GetItem(args, 0);
1896 if (PyTuple_Check(o)) {
1897 o = SplitObj(o);
1898 return o;
1899 }
1900 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001901 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001902 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001903 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001904}
1905
1906static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001907Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001908{
Barry Warsawfa701a81997-01-16 00:15:11 +00001909 char *s = Merge(args);
1910 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001911
Barry Warsawfa701a81997-01-16 00:15:11 +00001912 if (s) {
1913 res = PyString_FromString(s);
1914 ckfree(s);
1915 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001916
1917 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001918}
1919
Barry Warsawfa701a81997-01-16 00:15:11 +00001920
1921
Guido van Rossum18468821994-06-20 07:49:28 +00001922/** Tcl Command **/
1923
Guido van Rossum00d93061998-05-28 23:06:38 +00001924/* Client data struct */
1925typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001926 PyObject *self;
1927 PyObject *func;
1928} PythonCmd_ClientData;
1929
1930static int
Fred Drake509d79a2000-07-08 04:04:38 +00001931PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001932{
1933 errorInCmd = 1;
1934 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1935 LEAVE_PYTHON
1936 return TCL_ERROR;
1937}
1938
Guido van Rossum18468821994-06-20 07:49:28 +00001939/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001940 * function or method.
1941 */
Guido van Rossum18468821994-06-20 07:49:28 +00001942static int
Fred Drake509d79a2000-07-08 04:04:38 +00001943PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001944{
Guido van Rossum00d93061998-05-28 23:06:38 +00001945 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001946 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001947 int i, rv;
1948 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001949
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001950 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001951
Barry Warsawfa701a81997-01-16 00:15:11 +00001952 /* TBD: no error checking here since we know, via the
1953 * Tkapp_CreateCommand() that the client data is a two-tuple
1954 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001955 self = data->self;
1956 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001957
Barry Warsawfa701a81997-01-16 00:15:11 +00001958 /* Create argument list (argv1, ..., argvN) */
1959 if (!(arg = PyTuple_New(argc - 1)))
1960 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001961
Barry Warsawfa701a81997-01-16 00:15:11 +00001962 for (i = 0; i < (argc - 1); i++) {
1963 PyObject *s = PyString_FromString(argv[i + 1]);
1964 if (!s || PyTuple_SetItem(arg, i, s)) {
1965 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001966 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001967 }
1968 }
1969 res = PyEval_CallObject(func, arg);
1970 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001971
Barry Warsawfa701a81997-01-16 00:15:11 +00001972 if (res == NULL)
1973 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001974
Barry Warsawfa701a81997-01-16 00:15:11 +00001975 if (!(tmp = PyList_New(0))) {
1976 Py_DECREF(res);
1977 return PythonCmd_Error(interp);
1978 }
1979
Guido van Rossum2834b972000-10-06 16:58:26 +00001980 s = AsString(res, tmp);
1981 if (s == NULL) {
1982 rv = PythonCmd_Error(interp);
1983 }
1984 else {
1985 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1986 rv = TCL_OK;
1987 }
1988
Barry Warsawfa701a81997-01-16 00:15:11 +00001989 Py_DECREF(res);
1990 Py_DECREF(tmp);
1991
Guido van Rossum00d93061998-05-28 23:06:38 +00001992 LEAVE_PYTHON
1993
Guido van Rossum2834b972000-10-06 16:58:26 +00001994 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001995}
1996
1997static void
Fred Drake509d79a2000-07-08 04:04:38 +00001998PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001999{
Guido van Rossum00d93061998-05-28 23:06:38 +00002000 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2001
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002002 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002003 Py_XDECREF(data->self);
2004 Py_XDECREF(data->func);
2005 PyMem_DEL(data);
2006 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002007}
2008
Barry Warsawfa701a81997-01-16 00:15:11 +00002009
2010
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002011
2012TCL_DECLARE_MUTEX(command_mutex)
2013
2014typedef struct CommandEvent{
2015 Tcl_Event ev;
2016 Tcl_Interp* interp;
2017 char *name;
2018 int create;
2019 int *status;
2020 ClientData *data;
2021 Tcl_Condition done;
2022} CommandEvent;
2023
2024static int
2025Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002026{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002027 if (ev->create)
2028 *ev->status = Tcl_CreateCommand(
2029 ev->interp, ev->name, PythonCmd,
2030 ev->data, PythonCmdDelete) == NULL;
2031 else
2032 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2033 Tcl_MutexLock(&command_mutex);
2034 Tcl_ConditionNotify(&ev->done);
2035 Tcl_MutexUnlock(&command_mutex);
2036 return 1;
2037}
2038
2039static PyObject *
2040Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2041{
2042 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002043 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002044 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002045 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002046 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002047
Guido van Rossum43713e52000-02-29 13:59:29 +00002048 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002049 return NULL;
2050 if (!PyCallable_Check(func)) {
2051 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002052 return NULL;
2053 }
Guido van Rossum18468821994-06-20 07:49:28 +00002054
Martin v. Löwisa9656492003-03-30 08:44:58 +00002055#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002056 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002057 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002058 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002059#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002060
Guido van Rossum00d93061998-05-28 23:06:38 +00002061 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002062 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002063 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002064 Py_XINCREF(self);
2065 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002066 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002067 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002068
2069 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2070 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2071 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2072 ev->interp = self->interp;
2073 ev->create = 1;
2074 ev->name = cmdName;
2075 ev->data = (ClientData)data;
2076 ev->status = &err;
2077 ev->done = NULL;
2078 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2079 }
2080 else {
2081 ENTER_TCL
2082 err = Tcl_CreateCommand(
2083 Tkapp_Interp(self), cmdName, PythonCmd,
2084 (ClientData)data, PythonCmdDelete) == NULL;
2085 LEAVE_TCL
2086 }
2087 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002088 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002089 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002090 return NULL;
2091 }
Guido van Rossum18468821994-06-20 07:49:28 +00002092
Barry Warsawfa701a81997-01-16 00:15:11 +00002093 Py_INCREF(Py_None);
2094 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002095}
2096
Barry Warsawfa701a81997-01-16 00:15:11 +00002097
2098
Guido van Rossum18468821994-06-20 07:49:28 +00002099static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002100Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002101{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002102 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002103 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002104 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002105
Guido van Rossum43713e52000-02-29 13:59:29 +00002106 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002107 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002108 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2109 CommandEvent *ev;
2110 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2111 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2112 ev->interp = self->interp;
2113 ev->create = 0;
2114 ev->name = cmdName;
2115 ev->status = &err;
2116 ev->done = NULL;
2117 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2118 &command_mutex);
2119 }
2120 else {
2121 ENTER_TCL
2122 err = Tcl_DeleteCommand(self->interp, cmdName);
2123 LEAVE_TCL
2124 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002125 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002126 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2127 return NULL;
2128 }
2129 Py_INCREF(Py_None);
2130 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002131}
2132
Barry Warsawfa701a81997-01-16 00:15:11 +00002133
2134
Guido van Rossum00d93061998-05-28 23:06:38 +00002135#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002136/** File Handler **/
2137
Guido van Rossum00d93061998-05-28 23:06:38 +00002138typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002139 PyObject *func;
2140 PyObject *file;
2141 int id;
2142 struct _fhcdata *next;
2143} FileHandler_ClientData;
2144
2145static FileHandler_ClientData *HeadFHCD;
2146
2147static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002148NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002149{
2150 FileHandler_ClientData *p;
2151 p = PyMem_NEW(FileHandler_ClientData, 1);
2152 if (p != NULL) {
2153 Py_XINCREF(func);
2154 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002155 p->func = func;
2156 p->file = file;
2157 p->id = id;
2158 p->next = HeadFHCD;
2159 HeadFHCD = p;
2160 }
2161 return p;
2162}
2163
2164static void
Fred Drake509d79a2000-07-08 04:04:38 +00002165DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002166{
2167 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002168
2169 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002170 while ((p = *pp) != NULL) {
2171 if (p->id == id) {
2172 *pp = p->next;
2173 Py_XDECREF(p->func);
2174 Py_XDECREF(p->file);
2175 PyMem_DEL(p);
2176 }
2177 else
2178 pp = &p->next;
2179 }
2180}
2181
Guido van Rossuma597dde1995-01-10 20:56:29 +00002182static void
Fred Drake509d79a2000-07-08 04:04:38 +00002183FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002184{
Guido van Rossum00d93061998-05-28 23:06:38 +00002185 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002186 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002187
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002188 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002189 func = data->func;
2190 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002191
Barry Warsawfa701a81997-01-16 00:15:11 +00002192 arg = Py_BuildValue("(Oi)", file, (long) mask);
2193 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002194 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002195
2196 if (res == NULL) {
2197 errorInCmd = 1;
2198 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2199 }
2200 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002201 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002202}
2203
Guido van Rossum18468821994-06-20 07:49:28 +00002204static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002205Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2206 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002207{
Guido van Rossum00d93061998-05-28 23:06:38 +00002208 FileHandler_ClientData *data;
2209 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002210 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002211
Guido van Rossum2834b972000-10-06 16:58:26 +00002212 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2213 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002214 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002215
Martin v. Löwisa9656492003-03-30 08:44:58 +00002216#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002217 if (!self && !tcl_lock) {
2218 /* We don't have the Tcl lock since Tcl is threaded. */
2219 PyErr_SetString(PyExc_RuntimeError,
2220 "_tkinter.createfilehandler not supported "
2221 "for threaded Tcl");
2222 return NULL;
2223 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002224#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002225
2226 if (self) {
2227 CHECK_TCL_APPARTMENT;
2228 }
2229
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002230 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002231 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002232 return NULL;
2233 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002234 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002235 return NULL;
2236 }
2237
Guido van Rossuma80649b2000-03-28 20:07:05 +00002238 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002239 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002240 return NULL;
2241
Barry Warsawfa701a81997-01-16 00:15:11 +00002242 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002243 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002244 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002245 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002246 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002247 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002248}
2249
2250static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002251Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002252{
Barry Warsawfa701a81997-01-16 00:15:11 +00002253 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002254 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002255
Guido van Rossum43713e52000-02-29 13:59:29 +00002256 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002257 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002258
Martin v. Löwisa9656492003-03-30 08:44:58 +00002259#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002260 if (!self && !tcl_lock) {
2261 /* We don't have the Tcl lock since Tcl is threaded. */
2262 PyErr_SetString(PyExc_RuntimeError,
2263 "_tkinter.deletefilehandler not supported "
2264 "for threaded Tcl");
2265 return NULL;
2266 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002267#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002268
2269 if (self) {
2270 CHECK_TCL_APPARTMENT;
2271 }
2272
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002273 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002274 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002275 return NULL;
2276
Guido van Rossuma80649b2000-03-28 20:07:05 +00002277 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002278
Barry Warsawfa701a81997-01-16 00:15:11 +00002279 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002280 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002281 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002282 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002283 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002284 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002285}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002286#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002287
Barry Warsawfa701a81997-01-16 00:15:11 +00002288
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002289/**** Tktt Object (timer token) ****/
2290
Jeremy Hylton938ace62002-07-17 16:30:39 +00002291static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002292
Guido van Rossum00d93061998-05-28 23:06:38 +00002293typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002294 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002295 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002296 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002297} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002298
2299static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002300Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002301{
Barry Warsawfa701a81997-01-16 00:15:11 +00002302 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002303 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002304
Guido van Rossum43713e52000-02-29 13:59:29 +00002305 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002306 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002307 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002308 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002309 v->token = NULL;
2310 }
2311 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002312 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002313 Py_DECREF(func);
2314 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002315 }
2316 Py_INCREF(Py_None);
2317 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002318}
2319
2320static PyMethodDef Tktt_methods[] =
2321{
Neal Norwitzb0493252002-03-31 14:44:22 +00002322 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002323 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002324};
2325
2326static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002327Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002328{
Barry Warsawfa701a81997-01-16 00:15:11 +00002329 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002330
Guido van Rossumb18618d2000-05-03 23:44:39 +00002331 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002332 if (v == NULL)
2333 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002334
Guido van Rossum00d93061998-05-28 23:06:38 +00002335 Py_INCREF(func);
2336 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002337 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002338
2339 /* Extra reference, deleted when called or when handler is deleted */
2340 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002341 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002342}
2343
2344static void
Fred Drake509d79a2000-07-08 04:04:38 +00002345Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002346{
Guido van Rossum00d93061998-05-28 23:06:38 +00002347 TkttObject *v = (TkttObject *)self;
2348 PyObject *func = v->func;
2349
2350 Py_XDECREF(func);
2351
Guido van Rossumb18618d2000-05-03 23:44:39 +00002352 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002353}
2354
Guido van Rossum597ac201998-05-12 14:36:19 +00002355static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002356Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002357{
Barry Warsawfa701a81997-01-16 00:15:11 +00002358 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002359 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002360
Tim Peters885d4572001-11-28 20:27:42 +00002361 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002362 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002363 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002364}
2365
2366static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002367Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002368{
Barry Warsawfa701a81997-01-16 00:15:11 +00002369 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002370}
2371
2372static PyTypeObject Tktt_Type =
2373{
Guido van Rossum35d43371997-08-02 00:09:09 +00002374 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002375 0, /*ob_size */
2376 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002377 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002378 0, /*tp_itemsize */
2379 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002380 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002381 Tktt_GetAttr, /*tp_getattr */
2382 0, /*tp_setattr */
2383 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002384 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002385 0, /*tp_as_number */
2386 0, /*tp_as_sequence */
2387 0, /*tp_as_mapping */
2388 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002389};
2390
Barry Warsawfa701a81997-01-16 00:15:11 +00002391
2392
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002393/** Timer Handler **/
2394
2395static void
Fred Drake509d79a2000-07-08 04:04:38 +00002396TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002397{
Guido van Rossum00d93061998-05-28 23:06:38 +00002398 TkttObject *v = (TkttObject *)clientData;
2399 PyObject *func = v->func;
2400 PyObject *res;
2401
2402 if (func == NULL)
2403 return;
2404
2405 v->func = NULL;
2406
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002407 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002408
2409 res = PyEval_CallObject(func, NULL);
2410 Py_DECREF(func);
2411 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002412
Barry Warsawfa701a81997-01-16 00:15:11 +00002413 if (res == NULL) {
2414 errorInCmd = 1;
2415 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2416 }
2417 else
2418 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002419
2420 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002421}
2422
2423static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002424Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002425{
Barry Warsawfa701a81997-01-16 00:15:11 +00002426 int milliseconds;
2427 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002428 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002429
Guido van Rossum2834b972000-10-06 16:58:26 +00002430 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2431 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002432 return NULL;
2433 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002434 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002435 return NULL;
2436 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002437
Martin v. Löwisa9656492003-03-30 08:44:58 +00002438#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002439 if (!self && !tcl_lock) {
2440 /* We don't have the Tcl lock since Tcl is threaded. */
2441 PyErr_SetString(PyExc_RuntimeError,
2442 "_tkinter.createtimerhandler not supported "
2443 "for threaded Tcl");
2444 return NULL;
2445 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002446#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002447
2448 if (self) {
2449 CHECK_TCL_APPARTMENT;
2450 }
2451
Guido van Rossum00d93061998-05-28 23:06:38 +00002452 v = Tktt_New(func);
2453 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2454 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002455
Guido van Rossum00d93061998-05-28 23:06:38 +00002456 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002457}
2458
Barry Warsawfa701a81997-01-16 00:15:11 +00002459
Guido van Rossum18468821994-06-20 07:49:28 +00002460/** Event Loop **/
2461
Guido van Rossum18468821994-06-20 07:49:28 +00002462static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002463Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002464{
Barry Warsawfa701a81997-01-16 00:15:11 +00002465 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002466 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002467#ifdef WITH_THREAD
2468 PyThreadState *tstate = PyThreadState_Get();
2469#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002470
Guido van Rossum43713e52000-02-29 13:59:29 +00002471 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002472 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002473
Martin v. Löwisa9656492003-03-30 08:44:58 +00002474#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002475 if (!self && !tcl_lock) {
2476 /* We don't have the Tcl lock since Tcl is threaded. */
2477 PyErr_SetString(PyExc_RuntimeError,
2478 "_tkinter.mainloop not supported "
2479 "for threaded Tcl");
2480 return NULL;
2481 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002482#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002483
2484 if (self) {
2485 CHECK_TCL_APPARTMENT;
2486 self->dispatching = 1;
2487 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002488
Barry Warsawfa701a81997-01-16 00:15:11 +00002489 quitMainLoop = 0;
2490 while (Tk_GetNumMainWindows() > threshold &&
2491 !quitMainLoop &&
2492 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002493 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002494 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002495
2496#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002497 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002498 /* Allow other Python threads to run. */
2499 ENTER_TCL
2500 result = Tcl_DoOneEvent(0);
2501 LEAVE_TCL
2502 }
2503 else {
2504 Py_BEGIN_ALLOW_THREADS
2505 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2506 tcl_tstate = tstate;
2507 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2508 tcl_tstate = NULL;
2509 if(tcl_lock)PyThread_release_lock(tcl_lock);
2510 if (result == 0)
2511 Sleep(20);
2512 Py_END_ALLOW_THREADS
2513 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002514#else
2515 result = Tcl_DoOneEvent(0);
2516#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002517
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002518 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002519 if (self)
2520 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002521 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002522 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002523 if (result < 0)
2524 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002525 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002526 if (self)
2527 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002528 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002529
Barry Warsawfa701a81997-01-16 00:15:11 +00002530 if (errorInCmd) {
2531 errorInCmd = 0;
2532 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2533 excInCmd = valInCmd = trbInCmd = NULL;
2534 return NULL;
2535 }
2536 Py_INCREF(Py_None);
2537 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002538}
2539
2540static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002541Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002542{
Guido van Rossum35d43371997-08-02 00:09:09 +00002543 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002544 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002545
Guido van Rossum43713e52000-02-29 13:59:29 +00002546 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002547 return NULL;
2548
Guido van Rossum00d93061998-05-28 23:06:38 +00002549 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002550 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002551 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002552 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002553}
2554
2555static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002556Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002557{
2558
Guido van Rossum43713e52000-02-29 13:59:29 +00002559 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002560 return NULL;
2561
2562 quitMainLoop = 1;
2563 Py_INCREF(Py_None);
2564 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002565}
2566
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002567static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002568Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002569{
2570
Guido van Rossum43713e52000-02-29 13:59:29 +00002571 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002572 return NULL;
2573
2574 return PyInt_FromLong((long)Tkapp_Interp(self));
2575}
2576
Barry Warsawfa701a81997-01-16 00:15:11 +00002577
Martin v. Löwisffad6332002-11-26 09:28:05 +00002578static PyObject *
2579Tkapp_WantObjects(PyObject *self, PyObject *args)
2580{
2581
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002582 int wantobjects;
2583 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002584 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002585 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002586
2587 Py_INCREF(Py_None);
2588 return Py_None;
2589}
2590
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002591static PyObject *
2592Tkapp_WillDispatch(PyObject *self, PyObject *args)
2593{
2594
2595 ((TkappObject*)self)->dispatching = 1;
2596
2597 Py_INCREF(Py_None);
2598 return Py_None;
2599}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002600
Barry Warsawfa701a81997-01-16 00:15:11 +00002601
Guido van Rossum18468821994-06-20 07:49:28 +00002602/**** Tkapp Method List ****/
2603
2604static PyMethodDef Tkapp_methods[] =
2605{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002606 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002607 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002608 {"call", Tkapp_Call, METH_OLDARGS},
2609 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2610 {"eval", Tkapp_Eval, METH_VARARGS},
2611 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2612 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2613 {"record", Tkapp_Record, METH_VARARGS},
2614 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2615 {"setvar", Tkapp_SetVar, METH_VARARGS},
2616 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2617 {"getvar", Tkapp_GetVar, METH_VARARGS},
2618 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2619 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2620 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2621 {"getint", Tkapp_GetInt, METH_VARARGS},
2622 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2623 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2624 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2625 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2626 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2627 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2628 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2629 {"split", Tkapp_Split, METH_VARARGS},
2630 {"merge", Tkapp_Merge, METH_OLDARGS},
2631 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2632 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002633#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002634 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2635 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002636#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002637 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2638 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2639 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2640 {"quit", Tkapp_Quit, METH_VARARGS},
2641 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002642 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002643};
2644
Barry Warsawfa701a81997-01-16 00:15:11 +00002645
2646
Guido van Rossum18468821994-06-20 07:49:28 +00002647/**** Tkapp Type Methods ****/
2648
2649static void
Fred Drake509d79a2000-07-08 04:04:38 +00002650Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002651{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002652 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002653 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002654 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002655 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002656 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002657 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002658}
2659
2660static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002661Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002662{
Guido van Rossum35d43371997-08-02 00:09:09 +00002663 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002664}
2665
2666static PyTypeObject Tkapp_Type =
2667{
Guido van Rossum35d43371997-08-02 00:09:09 +00002668 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002669 0, /*ob_size */
2670 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002671 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002672 0, /*tp_itemsize */
2673 Tkapp_Dealloc, /*tp_dealloc */
2674 0, /*tp_print */
2675 Tkapp_GetAttr, /*tp_getattr */
2676 0, /*tp_setattr */
2677 0, /*tp_compare */
2678 0, /*tp_repr */
2679 0, /*tp_as_number */
2680 0, /*tp_as_sequence */
2681 0, /*tp_as_mapping */
2682 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002683};
2684
Barry Warsawfa701a81997-01-16 00:15:11 +00002685
2686
Guido van Rossum18468821994-06-20 07:49:28 +00002687/**** Tkinter Module ****/
2688
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002689typedef struct {
2690 PyObject* tuple;
2691 int size; /* current size */
2692 int maxsize; /* allocated size */
2693} FlattenContext;
2694
2695static int
2696_bump(FlattenContext* context, int size)
2697{
Guido van Rossum2834b972000-10-06 16:58:26 +00002698 /* expand tuple to hold (at least) size new items.
2699 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002700
2701 int maxsize = context->maxsize * 2;
2702
2703 if (maxsize < context->size + size)
2704 maxsize = context->size + size;
2705
2706 context->maxsize = maxsize;
2707
Tim Peters4324aa32001-05-28 22:30:08 +00002708 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002709}
2710
2711static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002712_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002713{
2714 /* add tuple or list to argument tuple (recursively) */
2715
2716 int i, size;
2717
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002718 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002719 PyErr_SetString(PyExc_ValueError,
2720 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002721 return 0;
2722 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002723 size = PyList_GET_SIZE(item);
2724 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002725 if (context->size + size > context->maxsize &&
2726 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002727 return 0;
2728 /* copy items to output tuple */
2729 for (i = 0; i < size; i++) {
2730 PyObject *o = PyList_GET_ITEM(item, i);
2731 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002732 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002733 return 0;
2734 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002735 if (context->size + 1 > context->maxsize &&
2736 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002737 return 0;
2738 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002739 PyTuple_SET_ITEM(context->tuple,
2740 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002741 }
2742 }
2743 } else if (PyTuple_Check(item)) {
2744 /* same, for tuples */
2745 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002746 if (context->size + size > context->maxsize &&
2747 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002748 return 0;
2749 for (i = 0; i < size; i++) {
2750 PyObject *o = PyTuple_GET_ITEM(item, i);
2751 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002752 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002753 return 0;
2754 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002755 if (context->size + 1 > context->maxsize &&
2756 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002757 return 0;
2758 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002759 PyTuple_SET_ITEM(context->tuple,
2760 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002761 }
2762 }
2763 } else {
2764 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2765 return 0;
2766 }
2767 return 1;
2768}
2769
2770static PyObject *
2771Tkinter_Flatten(PyObject* self, PyObject* args)
2772{
2773 FlattenContext context;
2774 PyObject* item;
2775
2776 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2777 return NULL;
2778
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002779 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002780 if (context.maxsize <= 0)
2781 return PyTuple_New(0);
2782
2783 context.tuple = PyTuple_New(context.maxsize);
2784 if (!context.tuple)
2785 return NULL;
2786
2787 context.size = 0;
2788
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002789 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002790 return NULL;
2791
Tim Peters4324aa32001-05-28 22:30:08 +00002792 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002793 return NULL;
2794
2795 return context.tuple;
2796}
2797
Guido van Rossum18468821994-06-20 07:49:28 +00002798static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002799Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002800{
Barry Warsawfa701a81997-01-16 00:15:11 +00002801 char *screenName = NULL;
2802 char *baseName = NULL;
2803 char *className = NULL;
2804 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002805 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002806
Guido van Rossum35d43371997-08-02 00:09:09 +00002807 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002808 if (baseName != NULL)
2809 baseName++;
2810 else
2811 baseName = Py_GetProgramName();
2812 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002813
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002814 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002815 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002816 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002817 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002818
Barry Warsawfa701a81997-01-16 00:15:11 +00002819 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002820 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002821}
2822
2823static PyMethodDef moduleMethods[] =
2824{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002825 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2826 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002827#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002828 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2829 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002830#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002831 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2832 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2833 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2834 {"quit", Tkapp_Quit, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002835 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002836};
2837
Guido van Rossum7bf15641998-05-22 18:28:17 +00002838#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002839
2840static int stdin_ready = 0;
2841
Guido van Rossumad4db171998-06-13 13:56:28 +00002842#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002843static void
Fred Drake509d79a2000-07-08 04:04:38 +00002844MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002845{
2846 stdin_ready = 1;
2847}
Guido van Rossumad4db171998-06-13 13:56:28 +00002848#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002849
Martin v. Löwisa9656492003-03-30 08:44:58 +00002850#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002851static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002852#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002853
Guido van Rossum18468821994-06-20 07:49:28 +00002854static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002855EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002856{
Guido van Rossumad4db171998-06-13 13:56:28 +00002857#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002858 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002859#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002860#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002861 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002862#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002863 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002864 errorInCmd = 0;
2865#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002866 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002867 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002868#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002869 while (!errorInCmd && !stdin_ready) {
2870 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002871#ifdef MS_WINDOWS
2872 if (_kbhit()) {
2873 stdin_ready = 1;
2874 break;
2875 }
2876#endif
2877#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002878 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002879 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002880 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002881
Guido van Rossum00d93061998-05-28 23:06:38 +00002882 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002883
2884 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002885 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002886 if (result == 0)
2887 Sleep(20);
2888 Py_END_ALLOW_THREADS
2889#else
2890 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002891#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002892
2893 if (result < 0)
2894 break;
2895 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002896#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002897 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002898#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002899 if (errorInCmd) {
2900 errorInCmd = 0;
2901 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2902 excInCmd = valInCmd = trbInCmd = NULL;
2903 PyErr_Print();
2904 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002905#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002906 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002907#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002908 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002909}
Guido van Rossum18468821994-06-20 07:49:28 +00002910
Guido van Rossum00d93061998-05-28 23:06:38 +00002911#endif
2912
Guido van Rossum7bf15641998-05-22 18:28:17 +00002913static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002914EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002915{
Guido van Rossum00d93061998-05-28 23:06:38 +00002916#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002917 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002918#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002919 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002920#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002921 PyOS_InputHook = EventHook;
2922 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002923#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002924}
2925
2926static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002927DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002928{
Guido van Rossum00d93061998-05-28 23:06:38 +00002929#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002930 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2931 PyOS_InputHook = NULL;
2932 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002933#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002934}
2935
Barry Warsawfa701a81997-01-16 00:15:11 +00002936
2937/* all errors will be checked in one fell swoop in init_tkinter() */
2938static void
Fred Drake509d79a2000-07-08 04:04:38 +00002939ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002940{
2941 PyObject *v = PyInt_FromLong(val);
2942 if (v) {
2943 PyDict_SetItemString(d, name, v);
2944 Py_DECREF(v);
2945 }
2946}
2947static void
Fred Drake509d79a2000-07-08 04:04:38 +00002948ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002949{
2950 PyObject *v = PyString_FromString(val);
2951 if (v) {
2952 PyDict_SetItemString(d, name, v);
2953 Py_DECREF(v);
2954 }
2955}
2956
2957
Mark Hammond62b1ab12002-07-23 06:31:15 +00002958PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002959init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002960{
Barry Warsawfa701a81997-01-16 00:15:11 +00002961 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002962
Barry Warsawfa701a81997-01-16 00:15:11 +00002963 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002964
2965#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002966 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002967#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002968
Barry Warsawfa701a81997-01-16 00:15:11 +00002969 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002970
Barry Warsawfa701a81997-01-16 00:15:11 +00002971 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00002972 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00002973 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002974
Guido van Rossum35d43371997-08-02 00:09:09 +00002975 ins_long(d, "READABLE", TCL_READABLE);
2976 ins_long(d, "WRITABLE", TCL_WRITABLE);
2977 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2978 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2979 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2980 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2981 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2982 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2983 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002984 ins_string(d, "TK_VERSION", TK_VERSION);
2985 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002986
Guido van Rossum83551bf1997-09-13 00:44:23 +00002987 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002988
2989 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002990 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2991
Martin v. Löwisffad6332002-11-26 09:28:05 +00002992 PyTclObject_Type.ob_type = &PyType_Type;
2993 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002994
2995#ifdef TK_AQUA
2996 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2997 * start waking up. Note that Tcl_FindExecutable will do this, this
2998 * code must be above it! The original warning from
2999 * tkMacOSXAppInit.c is copied below.
3000 *
3001 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3002 * Tcl interpreter for now. It probably should work to do this
3003 * in the other order, but for now it doesn't seem to.
3004 *
3005 */
3006 Tk_MacOSXSetupTkNotifier();
3007#endif
3008
3009
Guido van Rossume187b0e2000-03-27 21:46:29 +00003010 /* This helps the dynamic loader; in Unicode aware Tcl versions
3011 it also helps Tcl find its encodings. */
3012 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003013
Barry Warsawfa701a81997-01-16 00:15:11 +00003014 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003015 return;
3016
Guido van Rossum43ff8681998-07-14 18:02:13 +00003017#if 0
3018 /* This was not a good idea; through <Destroy> bindings,
3019 Tcl_Finalize() may invoke Python code but at that point the
3020 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003021 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003022#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003023
Jack Jansen34cc5c31995-10-31 16:15:12 +00003024#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003025 /*
3026 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
3027 ** Most of the initializations in that routine (toolbox init calls and
3028 ** such) have already been done for us, so we only need these.
3029 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003030 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003031
3032 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00003033#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00003034 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00003035#endif /* GENERATINGCFM */
3036#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00003037}
Guido van Rossum9722ad81995-09-22 23:49:28 +00003038
Guido van Rossumec22c921996-02-25 04:50:29 +00003039
Barry Warsawfa701a81997-01-16 00:15:11 +00003040
Guido van Rossum9722ad81995-09-22 23:49:28 +00003041#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003042
3043/*
Guido van Rossumec22c921996-02-25 04:50:29 +00003044** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003045*/
3046
Guido van Rossum9722ad81995-09-22 23:49:28 +00003047void
3048panic(char * format, ...)
3049{
Barry Warsawfa701a81997-01-16 00:15:11 +00003050 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003051
Barry Warsawfa701a81997-01-16 00:15:11 +00003052 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003053
Guido van Rossum227cf761998-08-05 13:53:32 +00003054 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00003055 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003056
Barry Warsawfa701a81997-01-16 00:15:11 +00003057 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003058
Barry Warsawfa701a81997-01-16 00:15:11 +00003059 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00003060}
Jack Jansen40b546d1995-11-14 10:34:45 +00003061
Guido van Rossumec22c921996-02-25 04:50:29 +00003062/*
3063** Pass events to SIOUX before passing them to Tk.
3064*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003065
Guido van Rossumec22c921996-02-25 04:50:29 +00003066static int
Fred Drake509d79a2000-07-08 04:04:38 +00003067PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003068{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003069 WindowPtr frontwin;
3070 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00003071 ** Sioux eats too many events, so we don't pass it everything. We
3072 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003073 ** the Sioux window is frontmost. This means that Tk menus don't work
3074 ** in that case, but at least we can scroll the sioux window.
3075 ** Note that the SIOUXIsAppWindow() routine we use here is not really
3076 ** part of the external interface of Sioux...
3077 */
3078 frontwin = FrontWindow();
3079 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
3080 if (SIOUXHandleOneEvent(eventPtr))
3081 return 0; /* Nothing happened to the Tcl event queue */
3082 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003083 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003084}
3085
Guido van Rossumec22c921996-02-25 04:50:29 +00003086#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003087
3088/*
3089** Additional Mac specific code for dealing with shared libraries.
3090*/
3091
3092#include <Resources.h>
3093#include <CodeFragments.h>
3094
3095static int loaded_from_shlib = 0;
3096static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003097
Jack Jansen34cc5c31995-10-31 16:15:12 +00003098/*
3099** If this module is dynamically loaded the following routine should
3100** be the init routine. It takes care of adding the shared library to
3101** the resource-file chain, so that the tk routines can find their
3102** resources.
3103*/
3104OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003105init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003106{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00003107 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00003108 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003109 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003110 library_fss = *data->fragLocator.u.onDisk.fileSpec;
3111 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003112 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003113 library_fss = *data->fragLocator.u.inSegs.fileSpec;
3114 loaded_from_shlib = 1;
3115 }
3116 return noErr;
3117}
3118
3119/*
3120** Insert the library resources into the search path. Put them after
3121** the resources from the application. Again, we ignore errors.
3122*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003123static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003124mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003125{
3126 if ( !loaded_from_shlib )
3127 return;
3128 (void)FSpOpenResFile(&library_fss, fsRdPerm);
3129}
3130
Guido van Rossumec22c921996-02-25 04:50:29 +00003131#endif /* GENERATINGCFM */
3132#endif /* macintosh */