blob: a61bf7f3abcf76597ef0c4acca773f146aa4e1e6 [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öwisdd6cd652003-05-03 09:45:12 +0000813static int
814PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
815{
816 int res;
817 res = strcmp(Tcl_GetString(self->value),
818 Tcl_GetString(other->value));
819 if (res < 0) return -1;
820 if (res > 0) return 1;
821 return 0;
822}
823
Martin v. Löwis39195712003-01-04 00:33:13 +0000824PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
825
Martin v. Löwisffad6332002-11-26 09:28:05 +0000826static PyObject*
827get_typename(PyTclObject* obj, void* ignored)
828{
829 return PyString_FromString(obj->value->typePtr->name);
830}
831
Martin v. Löwis39195712003-01-04 00:33:13 +0000832
Martin v. Löwisffad6332002-11-26 09:28:05 +0000833static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000834 {"typename", (getter)get_typename, NULL, get_typename__doc__},
835 {"string", (getter)PyTclObject_string, NULL,
836 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000837 {0},
838};
839
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000840static PyMethodDef PyTclObject_methods[] = {
841 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000842 PyTclObject_unicode__doc__},
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000843 {0}
844};
845
Martin v. Löwisffad6332002-11-26 09:28:05 +0000846statichere PyTypeObject PyTclObject_Type = {
847 PyObject_HEAD_INIT(NULL)
848 0, /*ob_size*/
849 "_tkinter.Tcl_Obj", /*tp_name*/
850 sizeof(PyTclObject), /*tp_basicsize*/
851 0, /*tp_itemsize*/
852 /* methods */
853 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
854 0, /*tp_print*/
855 0, /*tp_getattr*/
856 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000857 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000858 (reprfunc)PyTclObject_repr, /*tp_repr*/
859 0, /*tp_as_number*/
860 0, /*tp_as_sequence*/
861 0, /*tp_as_mapping*/
862 0, /*tp_hash*/
863 0, /*tp_call*/
864 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000865 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000866 0, /*tp_setattro*/
867 0, /*tp_as_buffer*/
868 Py_TPFLAGS_DEFAULT, /*tp_flags*/
869 0, /*tp_doc*/
870 0, /*tp_traverse*/
871 0, /*tp_clear*/
872 0, /*tp_richcompare*/
873 0, /*tp_weaklistoffset*/
874 0, /*tp_iter*/
875 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000876 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000877 0, /*tp_members*/
878 PyTclObject_getsetlist, /*tp_getset*/
879 0, /*tp_base*/
880 0, /*tp_dict*/
881 0, /*tp_descr_get*/
882 0, /*tp_descr_set*/
883 0, /*tp_dictoffset*/
884 0, /*tp_init*/
885 0, /*tp_alloc*/
886 0, /*tp_new*/
887 0, /*tp_free*/
888 0, /*tp_is_gc*/
889};
890
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000891static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000892AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000893{
894 Tcl_Obj *result;
895
896 if (PyString_Check(value))
897 return Tcl_NewStringObj(PyString_AS_STRING(value),
898 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000899 else if (PyBool_Check(value))
900 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000901 else if (PyInt_Check(value))
902 return Tcl_NewLongObj(PyInt_AS_LONG(value));
903 else if (PyFloat_Check(value))
904 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
905 else if (PyTuple_Check(value)) {
906 Tcl_Obj **argv = (Tcl_Obj**)
907 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
908 int i;
909 if(!argv)
910 return 0;
911 for(i=0;i<PyTuple_Size(value);i++)
912 argv[i] = AsObj(PyTuple_GetItem(value,i));
913 result = Tcl_NewListObj(PyTuple_Size(value), argv);
914 ckfree(FREECAST argv);
915 return result;
916 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000917#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000918 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000919 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
920 int size = PyUnicode_GET_SIZE(value);
921 /* This #ifdef assumes that Tcl uses UCS-2.
922 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000923#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000924 Tcl_UniChar *outbuf;
925 int i;
926 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
927 if (!outbuf) {
928 PyErr_NoMemory();
929 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000930 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000931 for (i = 0; i < size; i++) {
932 if (inbuf[i] >= 0x10000) {
933 /* Tcl doesn't do UTF-16, yet. */
934 PyErr_SetString(PyExc_ValueError,
935 "unsupported character");
936 ckfree(FREECAST outbuf);
937 return NULL;
938 }
939 outbuf[i] = inbuf[i];
940 }
941 result = Tcl_NewUnicodeObj(outbuf, size);
942 ckfree(FREECAST outbuf);
943 return result;
944#else
945 return Tcl_NewUnicodeObj(inbuf, size);
946#endif
947
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000948 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000949#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000950 else if(PyTclObject_Check(value)) {
951 Tcl_Obj *v = ((PyTclObject*)value)->value;
952 Tcl_IncrRefCount(v);
953 return v;
954 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000955 else {
956 PyObject *v = PyObject_Str(value);
957 if (!v)
958 return 0;
959 result = AsObj(v);
960 Py_DECREF(v);
961 return result;
962 }
963}
964
Martin v. Löwisffad6332002-11-26 09:28:05 +0000965static PyObject*
966FromObj(PyObject* tkapp, Tcl_Obj *value)
967{
968 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000969 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000970
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000971 if (value->typePtr == NULL) {
972 /* If the result contains any bytes with the top bit set,
973 it's UTF-8 and we should decode it to Unicode */
974#ifdef Py_USING_UNICODE
975 int i;
976 char *s = value->bytes;
977 int len = value->length;
978 for (i = 0; i < len; i++) {
979 if (value->bytes[i] & 0x80)
980 break;
981 }
982
983 if (i == value->length)
984 result = PyString_FromStringAndSize(s, len);
985 else {
986 /* Convert UTF-8 to Unicode string */
987 result = PyUnicode_DecodeUTF8(s, len, "strict");
988 if (result == NULL) {
989 PyErr_Clear();
990 result = PyString_FromStringAndSize(s, len);
991 }
992 }
993#else
994 res = PyString_FromStringAndSize(value->bytes, value->length);
995#endif
996 return result;
997 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000998
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000999 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001000 result = value->internalRep.longValue ? Py_True : Py_False;
1001 Py_INCREF(result);
1002 return result;
1003 }
1004
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001005 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001006 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +00001007 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001008 return PyString_FromStringAndSize(data, size);
1009 }
1010
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001011 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001012 return PyFloat_FromDouble(value->internalRep.doubleValue);
1013 }
1014
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001015 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001016 return PyInt_FromLong(value->internalRep.longValue);
1017 }
1018
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001019 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001020 int size;
1021 int i, status;
1022 PyObject *elem;
1023 Tcl_Obj *tcl_elem;
1024
1025 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1026 if (status == TCL_ERROR)
1027 return Tkinter_Error(tkapp);
1028 result = PyTuple_New(size);
1029 if (!result)
1030 return NULL;
1031 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001032 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001033 value, i, &tcl_elem);
1034 if (status == TCL_ERROR) {
1035 Py_DECREF(result);
1036 return Tkinter_Error(tkapp);
1037 }
1038 elem = FromObj(tkapp, tcl_elem);
1039 if (!elem) {
1040 Py_DECREF(result);
1041 return NULL;
1042 }
1043 PyTuple_SetItem(result, i, elem);
1044 }
1045 return result;
1046 }
1047
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001048 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001049 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001050 }
1051
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001052 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001053#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001054#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001055 PyObject *result;
1056 int size;
1057 Tcl_UniChar *input;
1058 Py_UNICODE *output;
1059
1060 size = Tcl_GetCharLength(value);
1061 result = PyUnicode_FromUnicode(NULL, size);
1062 if (!result)
1063 return NULL;
1064 input = Tcl_GetUnicode(value);
1065 output = PyUnicode_AS_UNICODE(result);
1066 while (size--)
1067 *output++ = *input++;
1068 return result;
1069#else
1070 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1071 Tcl_GetCharLength(value));
1072#endif
1073#else
1074 int size;
1075 char *c;
1076 c = Tcl_GetStringFromObj(value, &size);
1077 return PyString_FromStringAndSize(c, size);
1078#endif
1079 }
1080
1081 return newPyTclObject(value);
1082}
1083
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001084/* This mutex synchronizes inter-thread command calls. */
1085
1086TCL_DECLARE_MUTEX(call_mutex)
1087
1088typedef struct Tkapp_CallEvent {
1089 Tcl_Event ev; /* Must be first */
1090 TkappObject *self;
1091 PyObject *args;
1092 int flags;
1093 PyObject **res;
1094 PyObject **exc_type, **exc_value, **exc_tb;
1095 Tcl_Condition done;
1096} Tkapp_CallEvent;
1097
1098void
1099Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001100{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001101 int i;
1102 for (i = 0; i < objc; i++)
1103 Tcl_DecrRefCount(objv[i]);
1104 if (objv != objStore)
1105 ckfree(FREECAST objv);
1106}
Guido van Rossum18468821994-06-20 07:49:28 +00001107
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001108/* Convert Python objects to Tcl objects. This must happen in the
1109 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001110
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001111static Tcl_Obj**
1112Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1113{
1114 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001115 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001116 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001117 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001118
Guido van Rossum212643f1998-04-29 16:22:14 +00001119 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001120 objv[0] = AsObj(args);
1121 if (objv[0] == 0)
1122 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001123 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001124 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001125 }
1126 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001127 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001128
Guido van Rossum632de272000-03-29 00:19:50 +00001129 if (objc > ARGSZ) {
1130 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1131 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001132 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001133 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001134 goto finally;
1135 }
1136 }
1137
Guido van Rossum632de272000-03-29 00:19:50 +00001138 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001139 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001140 if (v == Py_None) {
1141 objc = i;
1142 break;
1143 }
Guido van Rossum632de272000-03-29 00:19:50 +00001144 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001145 if (!objv[i]) {
1146 /* Reset objc, so it attempts to clear
1147 objects only up to i. */
1148 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001149 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001150 }
Guido van Rossum632de272000-03-29 00:19:50 +00001151 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001152 }
1153 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001154 *pobjc = objc;
1155 return objv;
1156finally:
1157 Tkapp_CallDeallocArgs(objv, objStore, objc);
1158 return NULL;
1159}
Guido van Rossum212643f1998-04-29 16:22:14 +00001160
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001161/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001162
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001163static PyObject*
1164Tkapp_CallResult(TkappObject *self)
1165{
1166 PyObject *res = NULL;
1167 if(self->wantobjects) {
1168 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001169 /* Not sure whether the IncrRef is necessary, but something
1170 may overwrite the interpreter result while we are
1171 converting it. */
1172 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001173 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001174 Tcl_DecrRefCount(value);
1175 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001176 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001177 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001178
Guido van Rossum990f5c62000-05-04 15:07:16 +00001179 /* If the result contains any bytes with the top bit set,
1180 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001181#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001182 while (*p != '\0') {
1183 if (*p & 0x80)
1184 break;
1185 p++;
1186 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001187
Guido van Rossum990f5c62000-05-04 15:07:16 +00001188 if (*p == '\0')
1189 res = PyString_FromStringAndSize(s, (int)(p-s));
1190 else {
1191 /* Convert UTF-8 to Unicode string */
1192 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001193 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1194 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001195 PyErr_Clear();
1196 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001197 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001198 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001199#else
1200 p = strchr(p, '\0');
1201 res = PyString_FromStringAndSize(s, (int)(p-s));
1202#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001203 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001204 return res;
1205}
Guido van Rossum632de272000-03-29 00:19:50 +00001206
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001207/* Tkapp_CallProc is the event procedure that is executed in the context of
1208 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1209 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001210
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001211static int
1212Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1213{
1214 Tcl_Obj *objStore[ARGSZ];
1215 Tcl_Obj **objv;
1216 int objc;
1217 int i;
1218 ENTER_PYTHON
1219 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1220 if (!objv) {
1221 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1222 *(e->res) = NULL;
1223 }
1224 LEAVE_PYTHON
1225 if (!objv)
1226 goto done;
1227 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1228 ENTER_PYTHON
1229 if (i == TCL_ERROR) {
1230 *(e->res) = NULL;
1231 *(e->exc_type) = NULL;
1232 *(e->exc_tb) = NULL;
1233 *(e->exc_value) = PyObject_CallFunction(
1234 Tkinter_TclError, "s",
1235 Tcl_GetStringResult(e->self->interp));
1236 }
1237 else {
1238 *(e->res) = Tkapp_CallResult(e->self);
1239 }
1240 LEAVE_PYTHON
1241 done:
1242 /* Wake up calling thread. */
1243 Tcl_MutexLock(&call_mutex);
1244 Tcl_ConditionNotify(&e->done);
1245 Tcl_MutexUnlock(&call_mutex);
1246 return 1;
1247}
1248
1249/* This is the main entry point for calling a Tcl command.
1250 It supports three cases, with regard to threading:
1251 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1252 the context of the calling thread.
1253 2. Tcl is threaded, caller of the command is in the interpreter thread:
1254 Execute the command in the calling thread. Since the Tcl lock will
1255 not be used, we can merge that with case 1.
1256 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1257 the interpreter thread. Allocation of Tcl objects needs to occur in the
1258 interpreter thread, so we ship the PyObject* args to the target thread,
1259 and perform processing there. */
1260
1261static PyObject *
1262Tkapp_Call(PyObject *_self, PyObject *args)
1263{
1264 Tcl_Obj *objStore[ARGSZ];
1265 Tcl_Obj **objv = NULL;
1266 int objc, i;
1267 PyObject *res = NULL;
1268 TkappObject *self = (TkappObject*)_self;
1269 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1270 int flags = TCL_EVAL_DIRECT;
1271
Martin v. Löwisa9656492003-03-30 08:44:58 +00001272#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001273 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1274 /* We cannot call the command directly. Instead, we must
1275 marshal the parameters to the interpreter thread. */
1276 Tkapp_CallEvent *ev;
1277 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001278 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001279 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001280 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1281 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1282 ev->self = self;
1283 ev->args = args;
1284 ev->res = &res;
1285 ev->exc_type = &exc_type;
1286 ev->exc_value = &exc_value;
1287 ev->exc_tb = &exc_tb;
1288 ev->done = (Tcl_Condition)0;
1289
1290 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1291
1292 if (res == NULL) {
1293 if (exc_type)
1294 PyErr_Restore(exc_type, exc_value, exc_tb);
1295 else
1296 PyErr_SetObject(Tkinter_TclError, exc_value);
1297 }
1298 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001299 else
1300#endif
1301 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001302
1303 objv = Tkapp_CallArgs(args, objStore, &objc);
1304 if (!objv)
1305 return NULL;
1306
1307 ENTER_TCL
1308
1309 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1310
1311 ENTER_OVERLAP
1312
1313 if (i == TCL_ERROR)
1314 Tkinter_Error(_self);
1315 else
1316 res = Tkapp_CallResult(self);
1317
1318 LEAVE_OVERLAP_TCL
1319
1320 Tkapp_CallDeallocArgs(objv, objStore, objc);
1321 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001322 return res;
1323}
1324
1325
1326static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001327Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001328{
Guido van Rossum212643f1998-04-29 16:22:14 +00001329 /* Could do the same here as for Tkapp_Call(), but this is not used
1330 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1331 way for the user to do what all its Global* variants do (save and
1332 reset the scope pointer, call the local version, restore the saved
1333 scope pointer). */
1334
Guido van Rossum62320c91998-06-15 04:36:09 +00001335 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001336 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001337
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001338 CHECK_TCL_APPARTMENT;
1339
Guido van Rossum62320c91998-06-15 04:36:09 +00001340 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001341 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001342 int err;
1343 ENTER_TCL
1344 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001345 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001346 if (err == TCL_ERROR)
1347 res = Tkinter_Error(self);
1348 else
1349 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001350 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001351 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001352 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001353
1354 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001355}
1356
1357static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001358Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001359{
Barry Warsawfa701a81997-01-16 00:15:11 +00001360 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001361 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001362 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001363
Guido van Rossum43713e52000-02-29 13:59:29 +00001364 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001365 return NULL;
1366
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001367 CHECK_TCL_APPARTMENT;
1368
Guido van Rossum00d93061998-05-28 23:06:38 +00001369 ENTER_TCL
1370 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001371 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001372 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001373 res = Tkinter_Error(self);
1374 else
1375 res = PyString_FromString(Tkapp_Result(self));
1376 LEAVE_OVERLAP_TCL
1377 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001378}
1379
1380static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001381Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001382{
Barry Warsawfa701a81997-01-16 00:15:11 +00001383 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001384 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001385 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001386
Guido van Rossum43713e52000-02-29 13:59:29 +00001387 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001388 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001389
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001390 CHECK_TCL_APPARTMENT;
1391
Guido van Rossum00d93061998-05-28 23:06:38 +00001392 ENTER_TCL
1393 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001394 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001395 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001396 res = Tkinter_Error(self);
1397 else
1398 res = PyString_FromString(Tkapp_Result(self));
1399 LEAVE_OVERLAP_TCL
1400 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001401}
1402
1403static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001404Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001405{
Barry Warsawfa701a81997-01-16 00:15:11 +00001406 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001407 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001408 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001409
Guido van Rossum43713e52000-02-29 13:59:29 +00001410 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001411 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001412
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001413 CHECK_TCL_APPARTMENT;
1414
Guido van Rossum00d93061998-05-28 23:06:38 +00001415 ENTER_TCL
1416 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001417 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001418 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001419 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001420
Guido van Rossum62320c91998-06-15 04:36:09 +00001421 else
1422 res = PyString_FromString(Tkapp_Result(self));
1423 LEAVE_OVERLAP_TCL
1424 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001425}
1426
1427static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001428Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001429{
Barry Warsawfa701a81997-01-16 00:15:11 +00001430 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001431 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001432 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001433
Guido van Rossum35d43371997-08-02 00:09:09 +00001434 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001435 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001436
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001437 CHECK_TCL_APPARTMENT;
1438
Guido van Rossum00d93061998-05-28 23:06:38 +00001439 ENTER_TCL
1440 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001441 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001442 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001443 res = Tkinter_Error(self);
1444 else
1445 res = PyString_FromString(Tkapp_Result(self));
1446 LEAVE_OVERLAP_TCL
1447 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001448}
1449
1450static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001451Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001452{
Barry Warsawfa701a81997-01-16 00:15:11 +00001453 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001454
Guido van Rossum43713e52000-02-29 13:59:29 +00001455 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001456 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001457 CHECK_TCL_APPARTMENT;
1458
Guido van Rossum00d93061998-05-28 23:06:38 +00001459 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001460 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001461 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001462
Barry Warsawfa701a81997-01-16 00:15:11 +00001463 Py_INCREF(Py_None);
1464 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001465}
1466
Barry Warsawfa701a81997-01-16 00:15:11 +00001467
1468
Guido van Rossum18468821994-06-20 07:49:28 +00001469/** Tcl Variable **/
1470
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001471TCL_DECLARE_MUTEX(var_mutex)
1472
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001473typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001474typedef struct VarEvent {
1475 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001476 PyObject *self;
1477 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001478 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001479 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001480 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001481 PyObject **exc_type;
1482 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001483 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001484} VarEvent;
1485
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001486static int
1487varname_converter(PyObject *in, void *_out)
1488{
1489 char **out = (char**)_out;
1490 if (PyString_Check(in)) {
1491 *out = PyString_AsString(in);
1492 return 1;
1493 }
1494 if (PyTclObject_Check(in)) {
1495 *out = PyTclObject_TclString(in);
1496 return 1;
1497 }
1498 /* XXX: Should give diagnostics. */
1499 return 0;
1500}
1501
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001502void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001503var_perform(VarEvent *ev)
1504{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001505 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1506 if (!*(ev->res)) {
1507 PyObject *exc, *val, *tb;
1508 PyErr_Fetch(&exc, &val, &tb);
1509 PyErr_NormalizeException(&exc, &val, &tb);
1510 *(ev->exc_type) = exc;
1511 *(ev->exc_val) = val;
1512 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001513 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001514
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001515}
1516
1517static int
1518var_proc(VarEvent* ev, int flags)
1519{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001520 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001521 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001522 Tcl_MutexLock(&var_mutex);
1523 Tcl_ConditionNotify(&ev->cond);
1524 Tcl_MutexUnlock(&var_mutex);
1525 LEAVE_PYTHON
1526 return 1;
1527}
1528
1529static PyObject*
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001530var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001531{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001532 TkappObject *self = (TkappObject*)_self;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001533#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001534 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001535 TkappObject *self = (TkappObject*)_self;
1536 VarEvent *ev;
1537 PyObject *res, *exc_type, *exc_val;
1538
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001539 /* The current thread is not the interpreter thread. Marshal
1540 the call to the interpreter thread, then wait for
1541 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001542 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001543 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001544
1545 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1546
1547 ev->self = _self;
1548 ev->args = args;
1549 ev->flags = flags;
1550 ev->func = func;
1551 ev->res = &res;
1552 ev->exc_type = &exc_type;
1553 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001554 ev->cond = NULL;
1555 ev->ev.proc = (Tcl_EventProc*)var_proc;
1556 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001557 if (!res) {
1558 PyErr_SetObject(exc_type, exc_val);
1559 Py_DECREF(exc_type);
1560 Py_DECREF(exc_val);
1561 return NULL;
1562 }
1563 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001564 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001565#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001566 /* Tcl is not threaded, or this is the interpreter thread. */
1567 return func(_self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001568}
1569
Guido van Rossum18468821994-06-20 07:49:28 +00001570static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001571SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001572{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001573 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001574 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001575 PyObject *res = NULL;
1576 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001577
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001578 if (PyArg_ParseTuple(args, "O&O:setvar",
1579 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001580 /* XXX Acquire tcl lock??? */
1581 newval = AsObj(newValue);
1582 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001583 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001584 ENTER_TCL
1585 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1586 newval, flags);
1587 ENTER_OVERLAP
1588 if (!ok)
1589 Tkinter_Error(self);
1590 else {
1591 res = Py_None;
1592 Py_INCREF(res);
1593 }
1594 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001595 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001596 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001597 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001598 if (PyArg_ParseTuple(args, "ssO:setvar",
1599 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001600 /* XXX must hold tcl lock already??? */
1601 newval = AsObj(newValue);
1602 ENTER_TCL
1603 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1604 ENTER_OVERLAP
1605 if (!ok)
1606 Tkinter_Error(self);
1607 else {
1608 res = Py_None;
1609 Py_INCREF(res);
1610 }
1611 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001612 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001613 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001614 return NULL;
1615 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001616 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001617 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001618}
1619
1620static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001621Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001622{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001623 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001624}
1625
1626static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001627Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001628{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001629 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001630}
1631
Barry Warsawfa701a81997-01-16 00:15:11 +00001632
1633
Guido van Rossum18468821994-06-20 07:49:28 +00001634static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001635GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001636{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001637 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001638 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001639 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001640
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001641 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1642 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001643 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001644
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001645 ENTER_TCL
1646 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1647 ENTER_OVERLAP
1648 res = FromObj(self, tres);
1649 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001650 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001651}
1652
1653static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001654Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001655{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001656 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001657}
1658
1659static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001660Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001661{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001662 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001663}
1664
Barry Warsawfa701a81997-01-16 00:15:11 +00001665
1666
Guido van Rossum18468821994-06-20 07:49:28 +00001667static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001668UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001669{
Guido van Rossum35d43371997-08-02 00:09:09 +00001670 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001671 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001672 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001673
Guido van Rossum43713e52000-02-29 13:59:29 +00001674 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001675 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001676
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001677 ENTER_TCL
1678 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1679 ENTER_OVERLAP
1680 if (code == TCL_ERROR)
1681 res = Tkinter_Error(self);
1682 else {
1683 Py_INCREF(Py_None);
1684 res = Py_None;
1685 }
1686 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001687 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001688}
1689
1690static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001691Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001692{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001693 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001694}
1695
1696static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001697Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001698{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001699 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001700}
1701
Barry Warsawfa701a81997-01-16 00:15:11 +00001702
1703
Guido van Rossum18468821994-06-20 07:49:28 +00001704/** Tcl to Python **/
1705
1706static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001707Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001708{
Barry Warsawfa701a81997-01-16 00:15:11 +00001709 char *s;
1710 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001711
Martin v. Löwisffad6332002-11-26 09:28:05 +00001712 if (PyTuple_Size(args) == 1) {
1713 PyObject* o = PyTuple_GetItem(args, 0);
1714 if (PyInt_Check(o)) {
1715 Py_INCREF(o);
1716 return o;
1717 }
1718 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001719 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001720 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001721 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001722 return Tkinter_Error(self);
1723 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001724}
1725
1726static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001727Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001728{
Barry Warsawfa701a81997-01-16 00:15:11 +00001729 char *s;
1730 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001731
Martin v. Löwisffad6332002-11-26 09:28:05 +00001732 if (PyTuple_Size(args) == 1) {
1733 PyObject *o = PyTuple_GetItem(args, 0);
1734 if (PyFloat_Check(o)) {
1735 Py_INCREF(o);
1736 return o;
1737 }
1738 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001739 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001740 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001741 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001742 return Tkinter_Error(self);
1743 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001744}
1745
1746static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001747Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001748{
Barry Warsawfa701a81997-01-16 00:15:11 +00001749 char *s;
1750 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001751
Martin v. Löwisffad6332002-11-26 09:28:05 +00001752 if (PyTuple_Size(args) == 1) {
1753 PyObject *o = PyTuple_GetItem(args, 0);
1754 if (PyInt_Check(o)) {
1755 Py_INCREF(o);
1756 return o;
1757 }
1758 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001759 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001760 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001761 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1762 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001763 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001764}
1765
1766static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001767Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001768{
Barry Warsawfa701a81997-01-16 00:15:11 +00001769 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001770 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001771 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001772
Guido van Rossum43713e52000-02-29 13:59:29 +00001773 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001774 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001775
1776 CHECK_TCL_APPARTMENT;
1777
Guido van Rossum00d93061998-05-28 23:06:38 +00001778 ENTER_TCL
1779 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001780 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001781 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001782 res = Tkinter_Error(self);
1783 else
1784 res = Py_BuildValue("s", Tkapp_Result(self));
1785 LEAVE_OVERLAP_TCL
1786 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001787}
1788
1789static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001790Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001791{
Barry Warsawfa701a81997-01-16 00:15:11 +00001792 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001793 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001794 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001795 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001796
Guido van Rossum43713e52000-02-29 13:59:29 +00001797 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001798 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001799
1800 CHECK_TCL_APPARTMENT;
1801
Guido van Rossum00d93061998-05-28 23:06:38 +00001802 ENTER_TCL
1803 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001804 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001805 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001806 res = Tkinter_Error(self);
1807 else
1808 res = Py_BuildValue("l", v);
1809 LEAVE_OVERLAP_TCL
1810 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001811}
1812
1813static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001814Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001815{
Barry Warsawfa701a81997-01-16 00:15:11 +00001816 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001817 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001818 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001819 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001820
Guido van Rossum43713e52000-02-29 13:59:29 +00001821 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001822 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001823 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001824 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001825 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001826 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001827 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001828 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001829 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001830 res = Tkinter_Error(self);
1831 else
1832 res = Py_BuildValue("d", v);
1833 LEAVE_OVERLAP_TCL
1834 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001835}
1836
1837static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001838Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001839{
Barry Warsawfa701a81997-01-16 00:15:11 +00001840 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001841 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001842 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001843 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001844
Guido van Rossum43713e52000-02-29 13:59:29 +00001845 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001846 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001847 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001848 ENTER_TCL
1849 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001850 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001851 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001852 res = Tkinter_Error(self);
1853 else
1854 res = Py_BuildValue("i", v);
1855 LEAVE_OVERLAP_TCL
1856 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001857}
1858
Barry Warsawfa701a81997-01-16 00:15:11 +00001859
1860
Guido van Rossum18468821994-06-20 07:49:28 +00001861static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001862Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001863{
Barry Warsawfa701a81997-01-16 00:15:11 +00001864 char *list;
1865 int argc;
1866 char **argv;
1867 PyObject *v;
1868 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001869
Martin v. Löwisffad6332002-11-26 09:28:05 +00001870 if (PyTuple_Size(args) == 1) {
1871 v = PyTuple_GetItem(args, 0);
1872 if (PyTuple_Check(v)) {
1873 Py_INCREF(v);
1874 return v;
1875 }
1876 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001877 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001878 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001879
Barry Warsawfa701a81997-01-16 00:15:11 +00001880 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1881 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001882
Barry Warsawfa701a81997-01-16 00:15:11 +00001883 if (!(v = PyTuple_New(argc)))
1884 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001885
Barry Warsawfa701a81997-01-16 00:15:11 +00001886 for (i = 0; i < argc; i++) {
1887 PyObject *s = PyString_FromString(argv[i]);
1888 if (!s || PyTuple_SetItem(v, i, s)) {
1889 Py_DECREF(v);
1890 v = NULL;
1891 goto finally;
1892 }
1893 }
Guido van Rossum18468821994-06-20 07:49:28 +00001894
Barry Warsawfa701a81997-01-16 00:15:11 +00001895 finally:
1896 ckfree(FREECAST argv);
1897 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001898}
1899
1900static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001901Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001902{
Barry Warsawfa701a81997-01-16 00:15:11 +00001903 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001904
Martin v. Löwisffad6332002-11-26 09:28:05 +00001905 if (PyTuple_Size(args) == 1) {
1906 PyObject* o = PyTuple_GetItem(args, 0);
1907 if (PyTuple_Check(o)) {
1908 o = SplitObj(o);
1909 return o;
1910 }
1911 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001912 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001913 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001914 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001915}
1916
1917static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001918Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001919{
Barry Warsawfa701a81997-01-16 00:15:11 +00001920 char *s = Merge(args);
1921 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001922
Barry Warsawfa701a81997-01-16 00:15:11 +00001923 if (s) {
1924 res = PyString_FromString(s);
1925 ckfree(s);
1926 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001927
1928 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001929}
1930
Barry Warsawfa701a81997-01-16 00:15:11 +00001931
1932
Guido van Rossum18468821994-06-20 07:49:28 +00001933/** Tcl Command **/
1934
Guido van Rossum00d93061998-05-28 23:06:38 +00001935/* Client data struct */
1936typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001937 PyObject *self;
1938 PyObject *func;
1939} PythonCmd_ClientData;
1940
1941static int
Fred Drake509d79a2000-07-08 04:04:38 +00001942PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001943{
1944 errorInCmd = 1;
1945 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1946 LEAVE_PYTHON
1947 return TCL_ERROR;
1948}
1949
Guido van Rossum18468821994-06-20 07:49:28 +00001950/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001951 * function or method.
1952 */
Guido van Rossum18468821994-06-20 07:49:28 +00001953static int
Fred Drake509d79a2000-07-08 04:04:38 +00001954PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001955{
Guido van Rossum00d93061998-05-28 23:06:38 +00001956 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001957 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001958 int i, rv;
1959 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001960
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001961 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001962
Barry Warsawfa701a81997-01-16 00:15:11 +00001963 /* TBD: no error checking here since we know, via the
1964 * Tkapp_CreateCommand() that the client data is a two-tuple
1965 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001966 self = data->self;
1967 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001968
Barry Warsawfa701a81997-01-16 00:15:11 +00001969 /* Create argument list (argv1, ..., argvN) */
1970 if (!(arg = PyTuple_New(argc - 1)))
1971 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001972
Barry Warsawfa701a81997-01-16 00:15:11 +00001973 for (i = 0; i < (argc - 1); i++) {
1974 PyObject *s = PyString_FromString(argv[i + 1]);
1975 if (!s || PyTuple_SetItem(arg, i, s)) {
1976 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001977 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001978 }
1979 }
1980 res = PyEval_CallObject(func, arg);
1981 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001982
Barry Warsawfa701a81997-01-16 00:15:11 +00001983 if (res == NULL)
1984 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001985
Barry Warsawfa701a81997-01-16 00:15:11 +00001986 if (!(tmp = PyList_New(0))) {
1987 Py_DECREF(res);
1988 return PythonCmd_Error(interp);
1989 }
1990
Guido van Rossum2834b972000-10-06 16:58:26 +00001991 s = AsString(res, tmp);
1992 if (s == NULL) {
1993 rv = PythonCmd_Error(interp);
1994 }
1995 else {
1996 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1997 rv = TCL_OK;
1998 }
1999
Barry Warsawfa701a81997-01-16 00:15:11 +00002000 Py_DECREF(res);
2001 Py_DECREF(tmp);
2002
Guido van Rossum00d93061998-05-28 23:06:38 +00002003 LEAVE_PYTHON
2004
Guido van Rossum2834b972000-10-06 16:58:26 +00002005 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002006}
2007
2008static void
Fred Drake509d79a2000-07-08 04:04:38 +00002009PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002010{
Guido van Rossum00d93061998-05-28 23:06:38 +00002011 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2012
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002013 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002014 Py_XDECREF(data->self);
2015 Py_XDECREF(data->func);
2016 PyMem_DEL(data);
2017 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002018}
2019
Barry Warsawfa701a81997-01-16 00:15:11 +00002020
2021
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002022
2023TCL_DECLARE_MUTEX(command_mutex)
2024
2025typedef struct CommandEvent{
2026 Tcl_Event ev;
2027 Tcl_Interp* interp;
2028 char *name;
2029 int create;
2030 int *status;
2031 ClientData *data;
2032 Tcl_Condition done;
2033} CommandEvent;
2034
2035static int
2036Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002037{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002038 if (ev->create)
2039 *ev->status = Tcl_CreateCommand(
2040 ev->interp, ev->name, PythonCmd,
2041 ev->data, PythonCmdDelete) == NULL;
2042 else
2043 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2044 Tcl_MutexLock(&command_mutex);
2045 Tcl_ConditionNotify(&ev->done);
2046 Tcl_MutexUnlock(&command_mutex);
2047 return 1;
2048}
2049
2050static PyObject *
2051Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2052{
2053 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002054 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002055 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002056 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002057 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002058
Guido van Rossum43713e52000-02-29 13:59:29 +00002059 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002060 return NULL;
2061 if (!PyCallable_Check(func)) {
2062 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002063 return NULL;
2064 }
Guido van Rossum18468821994-06-20 07:49:28 +00002065
Martin v. Löwisa9656492003-03-30 08:44:58 +00002066#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002067 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002068 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002069 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002070#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002071
Guido van Rossum00d93061998-05-28 23:06:38 +00002072 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002073 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002074 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002075 Py_XINCREF(self);
2076 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002077 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002078 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002079
2080 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2081 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2082 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2083 ev->interp = self->interp;
2084 ev->create = 1;
2085 ev->name = cmdName;
2086 ev->data = (ClientData)data;
2087 ev->status = &err;
2088 ev->done = NULL;
2089 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2090 }
2091 else {
2092 ENTER_TCL
2093 err = Tcl_CreateCommand(
2094 Tkapp_Interp(self), cmdName, PythonCmd,
2095 (ClientData)data, PythonCmdDelete) == NULL;
2096 LEAVE_TCL
2097 }
2098 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002099 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002100 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002101 return NULL;
2102 }
Guido van Rossum18468821994-06-20 07:49:28 +00002103
Barry Warsawfa701a81997-01-16 00:15:11 +00002104 Py_INCREF(Py_None);
2105 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002106}
2107
Barry Warsawfa701a81997-01-16 00:15:11 +00002108
2109
Guido van Rossum18468821994-06-20 07:49:28 +00002110static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002111Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002112{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002113 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002114 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002115 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002116
Guido van Rossum43713e52000-02-29 13:59:29 +00002117 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002118 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002119 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2120 CommandEvent *ev;
2121 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2122 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2123 ev->interp = self->interp;
2124 ev->create = 0;
2125 ev->name = cmdName;
2126 ev->status = &err;
2127 ev->done = NULL;
2128 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2129 &command_mutex);
2130 }
2131 else {
2132 ENTER_TCL
2133 err = Tcl_DeleteCommand(self->interp, cmdName);
2134 LEAVE_TCL
2135 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002136 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002137 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2138 return NULL;
2139 }
2140 Py_INCREF(Py_None);
2141 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002142}
2143
Barry Warsawfa701a81997-01-16 00:15:11 +00002144
2145
Guido van Rossum00d93061998-05-28 23:06:38 +00002146#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002147/** File Handler **/
2148
Guido van Rossum00d93061998-05-28 23:06:38 +00002149typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002150 PyObject *func;
2151 PyObject *file;
2152 int id;
2153 struct _fhcdata *next;
2154} FileHandler_ClientData;
2155
2156static FileHandler_ClientData *HeadFHCD;
2157
2158static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002159NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002160{
2161 FileHandler_ClientData *p;
2162 p = PyMem_NEW(FileHandler_ClientData, 1);
2163 if (p != NULL) {
2164 Py_XINCREF(func);
2165 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002166 p->func = func;
2167 p->file = file;
2168 p->id = id;
2169 p->next = HeadFHCD;
2170 HeadFHCD = p;
2171 }
2172 return p;
2173}
2174
2175static void
Fred Drake509d79a2000-07-08 04:04:38 +00002176DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002177{
2178 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002179
2180 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002181 while ((p = *pp) != NULL) {
2182 if (p->id == id) {
2183 *pp = p->next;
2184 Py_XDECREF(p->func);
2185 Py_XDECREF(p->file);
2186 PyMem_DEL(p);
2187 }
2188 else
2189 pp = &p->next;
2190 }
2191}
2192
Guido van Rossuma597dde1995-01-10 20:56:29 +00002193static void
Fred Drake509d79a2000-07-08 04:04:38 +00002194FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002195{
Guido van Rossum00d93061998-05-28 23:06:38 +00002196 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002197 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002198
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002199 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002200 func = data->func;
2201 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002202
Barry Warsawfa701a81997-01-16 00:15:11 +00002203 arg = Py_BuildValue("(Oi)", file, (long) mask);
2204 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002205 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002206
2207 if (res == NULL) {
2208 errorInCmd = 1;
2209 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2210 }
2211 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002212 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002213}
2214
Guido van Rossum18468821994-06-20 07:49:28 +00002215static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002216Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2217 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002218{
Guido van Rossum00d93061998-05-28 23:06:38 +00002219 FileHandler_ClientData *data;
2220 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002221 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002222
Guido van Rossum2834b972000-10-06 16:58:26 +00002223 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2224 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002225 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002226
Martin v. Löwisa9656492003-03-30 08:44:58 +00002227#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002228 if (!self && !tcl_lock) {
2229 /* We don't have the Tcl lock since Tcl is threaded. */
2230 PyErr_SetString(PyExc_RuntimeError,
2231 "_tkinter.createfilehandler not supported "
2232 "for threaded Tcl");
2233 return NULL;
2234 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002235#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002236
2237 if (self) {
2238 CHECK_TCL_APPARTMENT;
2239 }
2240
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002241 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002242 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002243 return NULL;
2244 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002245 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002246 return NULL;
2247 }
2248
Guido van Rossuma80649b2000-03-28 20:07:05 +00002249 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002250 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002251 return NULL;
2252
Barry Warsawfa701a81997-01-16 00:15:11 +00002253 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002254 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002255 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002256 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002257 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002258 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002259}
2260
2261static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002262Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002263{
Barry Warsawfa701a81997-01-16 00:15:11 +00002264 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002265 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002266
Guido van Rossum43713e52000-02-29 13:59:29 +00002267 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002268 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002269
Martin v. Löwisa9656492003-03-30 08:44:58 +00002270#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002271 if (!self && !tcl_lock) {
2272 /* We don't have the Tcl lock since Tcl is threaded. */
2273 PyErr_SetString(PyExc_RuntimeError,
2274 "_tkinter.deletefilehandler not supported "
2275 "for threaded Tcl");
2276 return NULL;
2277 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002278#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002279
2280 if (self) {
2281 CHECK_TCL_APPARTMENT;
2282 }
2283
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002284 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002285 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002286 return NULL;
2287
Guido van Rossuma80649b2000-03-28 20:07:05 +00002288 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002289
Barry Warsawfa701a81997-01-16 00:15:11 +00002290 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002291 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002292 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002293 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002294 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002295 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002296}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002297#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002298
Barry Warsawfa701a81997-01-16 00:15:11 +00002299
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002300/**** Tktt Object (timer token) ****/
2301
Jeremy Hylton938ace62002-07-17 16:30:39 +00002302static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002303
Guido van Rossum00d93061998-05-28 23:06:38 +00002304typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002305 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002306 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002307 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002308} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002309
2310static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002311Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002312{
Barry Warsawfa701a81997-01-16 00:15:11 +00002313 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002314 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002315
Guido van Rossum43713e52000-02-29 13:59:29 +00002316 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002317 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002318 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002319 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002320 v->token = NULL;
2321 }
2322 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002323 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002324 Py_DECREF(func);
2325 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002326 }
2327 Py_INCREF(Py_None);
2328 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002329}
2330
2331static PyMethodDef Tktt_methods[] =
2332{
Neal Norwitzb0493252002-03-31 14:44:22 +00002333 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002334 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002335};
2336
2337static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002338Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002339{
Barry Warsawfa701a81997-01-16 00:15:11 +00002340 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002341
Guido van Rossumb18618d2000-05-03 23:44:39 +00002342 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002343 if (v == NULL)
2344 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002345
Guido van Rossum00d93061998-05-28 23:06:38 +00002346 Py_INCREF(func);
2347 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002348 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002349
2350 /* Extra reference, deleted when called or when handler is deleted */
2351 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002352 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002353}
2354
2355static void
Fred Drake509d79a2000-07-08 04:04:38 +00002356Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002357{
Guido van Rossum00d93061998-05-28 23:06:38 +00002358 TkttObject *v = (TkttObject *)self;
2359 PyObject *func = v->func;
2360
2361 Py_XDECREF(func);
2362
Guido van Rossumb18618d2000-05-03 23:44:39 +00002363 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002364}
2365
Guido van Rossum597ac201998-05-12 14:36:19 +00002366static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002367Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002368{
Barry Warsawfa701a81997-01-16 00:15:11 +00002369 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002370 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002371
Tim Peters885d4572001-11-28 20:27:42 +00002372 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002373 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002374 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002375}
2376
2377static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002378Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002379{
Barry Warsawfa701a81997-01-16 00:15:11 +00002380 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002381}
2382
2383static PyTypeObject Tktt_Type =
2384{
Guido van Rossum35d43371997-08-02 00:09:09 +00002385 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002386 0, /*ob_size */
2387 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002388 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002389 0, /*tp_itemsize */
2390 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002391 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002392 Tktt_GetAttr, /*tp_getattr */
2393 0, /*tp_setattr */
2394 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002395 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002396 0, /*tp_as_number */
2397 0, /*tp_as_sequence */
2398 0, /*tp_as_mapping */
2399 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002400};
2401
Barry Warsawfa701a81997-01-16 00:15:11 +00002402
2403
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002404/** Timer Handler **/
2405
2406static void
Fred Drake509d79a2000-07-08 04:04:38 +00002407TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002408{
Guido van Rossum00d93061998-05-28 23:06:38 +00002409 TkttObject *v = (TkttObject *)clientData;
2410 PyObject *func = v->func;
2411 PyObject *res;
2412
2413 if (func == NULL)
2414 return;
2415
2416 v->func = NULL;
2417
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002418 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002419
2420 res = PyEval_CallObject(func, NULL);
2421 Py_DECREF(func);
2422 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002423
Barry Warsawfa701a81997-01-16 00:15:11 +00002424 if (res == NULL) {
2425 errorInCmd = 1;
2426 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2427 }
2428 else
2429 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002430
2431 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002432}
2433
2434static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002435Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002436{
Barry Warsawfa701a81997-01-16 00:15:11 +00002437 int milliseconds;
2438 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002439 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002440
Guido van Rossum2834b972000-10-06 16:58:26 +00002441 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2442 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002443 return NULL;
2444 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002445 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002446 return NULL;
2447 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002448
Martin v. Löwisa9656492003-03-30 08:44:58 +00002449#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002450 if (!self && !tcl_lock) {
2451 /* We don't have the Tcl lock since Tcl is threaded. */
2452 PyErr_SetString(PyExc_RuntimeError,
2453 "_tkinter.createtimerhandler not supported "
2454 "for threaded Tcl");
2455 return NULL;
2456 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002457#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002458
2459 if (self) {
2460 CHECK_TCL_APPARTMENT;
2461 }
2462
Guido van Rossum00d93061998-05-28 23:06:38 +00002463 v = Tktt_New(func);
2464 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2465 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002466
Guido van Rossum00d93061998-05-28 23:06:38 +00002467 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002468}
2469
Barry Warsawfa701a81997-01-16 00:15:11 +00002470
Guido van Rossum18468821994-06-20 07:49:28 +00002471/** Event Loop **/
2472
Guido van Rossum18468821994-06-20 07:49:28 +00002473static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002474Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002475{
Barry Warsawfa701a81997-01-16 00:15:11 +00002476 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002477 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002478#ifdef WITH_THREAD
2479 PyThreadState *tstate = PyThreadState_Get();
2480#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002481
Guido van Rossum43713e52000-02-29 13:59:29 +00002482 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002483 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002484
Martin v. Löwisa9656492003-03-30 08:44:58 +00002485#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002486 if (!self && !tcl_lock) {
2487 /* We don't have the Tcl lock since Tcl is threaded. */
2488 PyErr_SetString(PyExc_RuntimeError,
2489 "_tkinter.mainloop not supported "
2490 "for threaded Tcl");
2491 return NULL;
2492 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002493#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002494
2495 if (self) {
2496 CHECK_TCL_APPARTMENT;
2497 self->dispatching = 1;
2498 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002499
Barry Warsawfa701a81997-01-16 00:15:11 +00002500 quitMainLoop = 0;
2501 while (Tk_GetNumMainWindows() > threshold &&
2502 !quitMainLoop &&
2503 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002504 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002505 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002506
2507#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002508 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002509 /* Allow other Python threads to run. */
2510 ENTER_TCL
2511 result = Tcl_DoOneEvent(0);
2512 LEAVE_TCL
2513 }
2514 else {
2515 Py_BEGIN_ALLOW_THREADS
2516 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2517 tcl_tstate = tstate;
2518 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2519 tcl_tstate = NULL;
2520 if(tcl_lock)PyThread_release_lock(tcl_lock);
2521 if (result == 0)
2522 Sleep(20);
2523 Py_END_ALLOW_THREADS
2524 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002525#else
2526 result = Tcl_DoOneEvent(0);
2527#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002528
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002529 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002530 if (self)
2531 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002532 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002533 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002534 if (result < 0)
2535 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002536 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002537 if (self)
2538 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002539 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002540
Barry Warsawfa701a81997-01-16 00:15:11 +00002541 if (errorInCmd) {
2542 errorInCmd = 0;
2543 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2544 excInCmd = valInCmd = trbInCmd = NULL;
2545 return NULL;
2546 }
2547 Py_INCREF(Py_None);
2548 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002549}
2550
2551static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002552Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002553{
Guido van Rossum35d43371997-08-02 00:09:09 +00002554 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002555 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002556
Guido van Rossum43713e52000-02-29 13:59:29 +00002557 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002558 return NULL;
2559
Guido van Rossum00d93061998-05-28 23:06:38 +00002560 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002561 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002562 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002563 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002564}
2565
2566static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002567Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002568{
2569
Guido van Rossum43713e52000-02-29 13:59:29 +00002570 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002571 return NULL;
2572
2573 quitMainLoop = 1;
2574 Py_INCREF(Py_None);
2575 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002576}
2577
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002578static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002579Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002580{
2581
Guido van Rossum43713e52000-02-29 13:59:29 +00002582 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002583 return NULL;
2584
2585 return PyInt_FromLong((long)Tkapp_Interp(self));
2586}
2587
Barry Warsawfa701a81997-01-16 00:15:11 +00002588
Martin v. Löwisffad6332002-11-26 09:28:05 +00002589static PyObject *
2590Tkapp_WantObjects(PyObject *self, PyObject *args)
2591{
2592
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002593 int wantobjects;
2594 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002595 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002596 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002597
2598 Py_INCREF(Py_None);
2599 return Py_None;
2600}
2601
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002602static PyObject *
2603Tkapp_WillDispatch(PyObject *self, PyObject *args)
2604{
2605
2606 ((TkappObject*)self)->dispatching = 1;
2607
2608 Py_INCREF(Py_None);
2609 return Py_None;
2610}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002611
Barry Warsawfa701a81997-01-16 00:15:11 +00002612
Guido van Rossum18468821994-06-20 07:49:28 +00002613/**** Tkapp Method List ****/
2614
2615static PyMethodDef Tkapp_methods[] =
2616{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002617 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002618 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002619 {"call", Tkapp_Call, METH_OLDARGS},
2620 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2621 {"eval", Tkapp_Eval, METH_VARARGS},
2622 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2623 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2624 {"record", Tkapp_Record, METH_VARARGS},
2625 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2626 {"setvar", Tkapp_SetVar, METH_VARARGS},
2627 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2628 {"getvar", Tkapp_GetVar, METH_VARARGS},
2629 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2630 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2631 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2632 {"getint", Tkapp_GetInt, METH_VARARGS},
2633 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2634 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2635 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2636 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2637 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2638 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2639 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2640 {"split", Tkapp_Split, METH_VARARGS},
2641 {"merge", Tkapp_Merge, METH_OLDARGS},
2642 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2643 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002644#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002645 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2646 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002647#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002648 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2649 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2650 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2651 {"quit", Tkapp_Quit, METH_VARARGS},
2652 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002653 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002654};
2655
Barry Warsawfa701a81997-01-16 00:15:11 +00002656
2657
Guido van Rossum18468821994-06-20 07:49:28 +00002658/**** Tkapp Type Methods ****/
2659
2660static void
Fred Drake509d79a2000-07-08 04:04:38 +00002661Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002662{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002663 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002664 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002665 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002666 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002667 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002668 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002669}
2670
2671static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002672Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002673{
Guido van Rossum35d43371997-08-02 00:09:09 +00002674 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002675}
2676
2677static PyTypeObject Tkapp_Type =
2678{
Guido van Rossum35d43371997-08-02 00:09:09 +00002679 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002680 0, /*ob_size */
2681 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002682 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002683 0, /*tp_itemsize */
2684 Tkapp_Dealloc, /*tp_dealloc */
2685 0, /*tp_print */
2686 Tkapp_GetAttr, /*tp_getattr */
2687 0, /*tp_setattr */
2688 0, /*tp_compare */
2689 0, /*tp_repr */
2690 0, /*tp_as_number */
2691 0, /*tp_as_sequence */
2692 0, /*tp_as_mapping */
2693 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002694};
2695
Barry Warsawfa701a81997-01-16 00:15:11 +00002696
2697
Guido van Rossum18468821994-06-20 07:49:28 +00002698/**** Tkinter Module ****/
2699
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002700typedef struct {
2701 PyObject* tuple;
2702 int size; /* current size */
2703 int maxsize; /* allocated size */
2704} FlattenContext;
2705
2706static int
2707_bump(FlattenContext* context, int size)
2708{
Guido van Rossum2834b972000-10-06 16:58:26 +00002709 /* expand tuple to hold (at least) size new items.
2710 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002711
2712 int maxsize = context->maxsize * 2;
2713
2714 if (maxsize < context->size + size)
2715 maxsize = context->size + size;
2716
2717 context->maxsize = maxsize;
2718
Tim Peters4324aa32001-05-28 22:30:08 +00002719 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002720}
2721
2722static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002723_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002724{
2725 /* add tuple or list to argument tuple (recursively) */
2726
2727 int i, size;
2728
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002729 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002730 PyErr_SetString(PyExc_ValueError,
2731 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002732 return 0;
2733 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002734 size = PyList_GET_SIZE(item);
2735 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002736 if (context->size + size > context->maxsize &&
2737 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002738 return 0;
2739 /* copy items to output tuple */
2740 for (i = 0; i < size; i++) {
2741 PyObject *o = PyList_GET_ITEM(item, i);
2742 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002743 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002744 return 0;
2745 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002746 if (context->size + 1 > context->maxsize &&
2747 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002748 return 0;
2749 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002750 PyTuple_SET_ITEM(context->tuple,
2751 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002752 }
2753 }
2754 } else if (PyTuple_Check(item)) {
2755 /* same, for tuples */
2756 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002757 if (context->size + size > context->maxsize &&
2758 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002759 return 0;
2760 for (i = 0; i < size; i++) {
2761 PyObject *o = PyTuple_GET_ITEM(item, i);
2762 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002763 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002764 return 0;
2765 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002766 if (context->size + 1 > context->maxsize &&
2767 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002768 return 0;
2769 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002770 PyTuple_SET_ITEM(context->tuple,
2771 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002772 }
2773 }
2774 } else {
2775 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2776 return 0;
2777 }
2778 return 1;
2779}
2780
2781static PyObject *
2782Tkinter_Flatten(PyObject* self, PyObject* args)
2783{
2784 FlattenContext context;
2785 PyObject* item;
2786
2787 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2788 return NULL;
2789
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002790 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002791 if (context.maxsize <= 0)
2792 return PyTuple_New(0);
2793
2794 context.tuple = PyTuple_New(context.maxsize);
2795 if (!context.tuple)
2796 return NULL;
2797
2798 context.size = 0;
2799
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002800 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002801 return NULL;
2802
Tim Peters4324aa32001-05-28 22:30:08 +00002803 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002804 return NULL;
2805
2806 return context.tuple;
2807}
2808
Guido van Rossum18468821994-06-20 07:49:28 +00002809static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002810Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002811{
Barry Warsawfa701a81997-01-16 00:15:11 +00002812 char *screenName = NULL;
2813 char *baseName = NULL;
2814 char *className = NULL;
2815 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002816 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002817
Guido van Rossum35d43371997-08-02 00:09:09 +00002818 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002819 if (baseName != NULL)
2820 baseName++;
2821 else
2822 baseName = Py_GetProgramName();
2823 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002824
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002825 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002826 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002827 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002828 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002829
Barry Warsawfa701a81997-01-16 00:15:11 +00002830 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002831 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002832}
2833
2834static PyMethodDef moduleMethods[] =
2835{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002836 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2837 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002838#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002839 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2840 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002841#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002842 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2843 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2844 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2845 {"quit", Tkapp_Quit, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002846 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002847};
2848
Guido van Rossum7bf15641998-05-22 18:28:17 +00002849#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002850
2851static int stdin_ready = 0;
2852
Guido van Rossumad4db171998-06-13 13:56:28 +00002853#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002854static void
Fred Drake509d79a2000-07-08 04:04:38 +00002855MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002856{
2857 stdin_ready = 1;
2858}
Guido van Rossumad4db171998-06-13 13:56:28 +00002859#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002860
Martin v. Löwisa9656492003-03-30 08:44:58 +00002861#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002862static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002863#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002864
Guido van Rossum18468821994-06-20 07:49:28 +00002865static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002866EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002867{
Guido van Rossumad4db171998-06-13 13:56:28 +00002868#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002869 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002870#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002871#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002872 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002873#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002874 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002875 errorInCmd = 0;
2876#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002877 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002878 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002879#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002880 while (!errorInCmd && !stdin_ready) {
2881 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002882#ifdef MS_WINDOWS
2883 if (_kbhit()) {
2884 stdin_ready = 1;
2885 break;
2886 }
2887#endif
2888#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002889 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002890 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002891 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002892
Guido van Rossum00d93061998-05-28 23:06:38 +00002893 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002894
2895 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002896 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002897 if (result == 0)
2898 Sleep(20);
2899 Py_END_ALLOW_THREADS
2900#else
2901 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002902#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002903
2904 if (result < 0)
2905 break;
2906 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002907#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002908 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002909#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002910 if (errorInCmd) {
2911 errorInCmd = 0;
2912 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2913 excInCmd = valInCmd = trbInCmd = NULL;
2914 PyErr_Print();
2915 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002916#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002917 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002918#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002919 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002920}
Guido van Rossum18468821994-06-20 07:49:28 +00002921
Guido van Rossum00d93061998-05-28 23:06:38 +00002922#endif
2923
Guido van Rossum7bf15641998-05-22 18:28:17 +00002924static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002925EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002926{
Guido van Rossum00d93061998-05-28 23:06:38 +00002927#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002928 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002929#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002930 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002931#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002932 PyOS_InputHook = EventHook;
2933 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002934#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002935}
2936
2937static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002938DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002939{
Guido van Rossum00d93061998-05-28 23:06:38 +00002940#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002941 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2942 PyOS_InputHook = NULL;
2943 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002944#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002945}
2946
Barry Warsawfa701a81997-01-16 00:15:11 +00002947
2948/* all errors will be checked in one fell swoop in init_tkinter() */
2949static void
Fred Drake509d79a2000-07-08 04:04:38 +00002950ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002951{
2952 PyObject *v = PyInt_FromLong(val);
2953 if (v) {
2954 PyDict_SetItemString(d, name, v);
2955 Py_DECREF(v);
2956 }
2957}
2958static void
Fred Drake509d79a2000-07-08 04:04:38 +00002959ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002960{
2961 PyObject *v = PyString_FromString(val);
2962 if (v) {
2963 PyDict_SetItemString(d, name, v);
2964 Py_DECREF(v);
2965 }
2966}
2967
2968
Mark Hammond62b1ab12002-07-23 06:31:15 +00002969PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002970init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002971{
Barry Warsawfa701a81997-01-16 00:15:11 +00002972 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002973
Barry Warsawfa701a81997-01-16 00:15:11 +00002974 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002975
2976#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002977 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002978#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002979
Barry Warsawfa701a81997-01-16 00:15:11 +00002980 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002981
Barry Warsawfa701a81997-01-16 00:15:11 +00002982 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00002983 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00002984 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002985
Guido van Rossum35d43371997-08-02 00:09:09 +00002986 ins_long(d, "READABLE", TCL_READABLE);
2987 ins_long(d, "WRITABLE", TCL_WRITABLE);
2988 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2989 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2990 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2991 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2992 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2993 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2994 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002995 ins_string(d, "TK_VERSION", TK_VERSION);
2996 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002997
Guido van Rossum83551bf1997-09-13 00:44:23 +00002998 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002999
3000 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003001 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3002
Martin v. Löwisffad6332002-11-26 09:28:05 +00003003 PyTclObject_Type.ob_type = &PyType_Type;
3004 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003005
3006#ifdef TK_AQUA
3007 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3008 * start waking up. Note that Tcl_FindExecutable will do this, this
3009 * code must be above it! The original warning from
3010 * tkMacOSXAppInit.c is copied below.
3011 *
3012 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3013 * Tcl interpreter for now. It probably should work to do this
3014 * in the other order, but for now it doesn't seem to.
3015 *
3016 */
3017 Tk_MacOSXSetupTkNotifier();
3018#endif
3019
3020
Guido van Rossume187b0e2000-03-27 21:46:29 +00003021 /* This helps the dynamic loader; in Unicode aware Tcl versions
3022 it also helps Tcl find its encodings. */
3023 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003024
Barry Warsawfa701a81997-01-16 00:15:11 +00003025 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003026 return;
3027
Guido van Rossum43ff8681998-07-14 18:02:13 +00003028#if 0
3029 /* This was not a good idea; through <Destroy> bindings,
3030 Tcl_Finalize() may invoke Python code but at that point the
3031 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003032 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003033#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003034
Jack Jansen34cc5c31995-10-31 16:15:12 +00003035#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003036 /*
3037 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
3038 ** Most of the initializations in that routine (toolbox init calls and
3039 ** such) have already been done for us, so we only need these.
3040 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003041 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003042
3043 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00003044#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00003045 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00003046#endif /* GENERATINGCFM */
3047#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00003048}
Guido van Rossum9722ad81995-09-22 23:49:28 +00003049
Guido van Rossumec22c921996-02-25 04:50:29 +00003050
Barry Warsawfa701a81997-01-16 00:15:11 +00003051
Guido van Rossum9722ad81995-09-22 23:49:28 +00003052#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003053
3054/*
Guido van Rossumec22c921996-02-25 04:50:29 +00003055** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003056*/
3057
Guido van Rossum9722ad81995-09-22 23:49:28 +00003058void
3059panic(char * format, ...)
3060{
Barry Warsawfa701a81997-01-16 00:15:11 +00003061 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003062
Barry Warsawfa701a81997-01-16 00:15:11 +00003063 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003064
Guido van Rossum227cf761998-08-05 13:53:32 +00003065 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00003066 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003067
Barry Warsawfa701a81997-01-16 00:15:11 +00003068 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003069
Barry Warsawfa701a81997-01-16 00:15:11 +00003070 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00003071}
Jack Jansen40b546d1995-11-14 10:34:45 +00003072
Guido van Rossumec22c921996-02-25 04:50:29 +00003073/*
3074** Pass events to SIOUX before passing them to Tk.
3075*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003076
Guido van Rossumec22c921996-02-25 04:50:29 +00003077static int
Fred Drake509d79a2000-07-08 04:04:38 +00003078PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003079{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003080 WindowPtr frontwin;
3081 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00003082 ** Sioux eats too many events, so we don't pass it everything. We
3083 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003084 ** the Sioux window is frontmost. This means that Tk menus don't work
3085 ** in that case, but at least we can scroll the sioux window.
3086 ** Note that the SIOUXIsAppWindow() routine we use here is not really
3087 ** part of the external interface of Sioux...
3088 */
3089 frontwin = FrontWindow();
3090 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
3091 if (SIOUXHandleOneEvent(eventPtr))
3092 return 0; /* Nothing happened to the Tcl event queue */
3093 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003094 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003095}
3096
Guido van Rossumec22c921996-02-25 04:50:29 +00003097#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003098
3099/*
3100** Additional Mac specific code for dealing with shared libraries.
3101*/
3102
3103#include <Resources.h>
3104#include <CodeFragments.h>
3105
3106static int loaded_from_shlib = 0;
3107static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003108
Jack Jansen34cc5c31995-10-31 16:15:12 +00003109/*
3110** If this module is dynamically loaded the following routine should
3111** be the init routine. It takes care of adding the shared library to
3112** the resource-file chain, so that the tk routines can find their
3113** resources.
3114*/
3115OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003116init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003117{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00003118 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00003119 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003120 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003121 library_fss = *data->fragLocator.u.onDisk.fileSpec;
3122 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003123 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003124 library_fss = *data->fragLocator.u.inSegs.fileSpec;
3125 loaded_from_shlib = 1;
3126 }
3127 return noErr;
3128}
3129
3130/*
3131** Insert the library resources into the search path. Put them after
3132** the resources from the application. Again, we ignore errors.
3133*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003134static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003135mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003136{
3137 if ( !loaded_from_shlib )
3138 return;
3139 (void)FSpOpenResFile(&library_fss, fsRdPerm);
3140}
3141
Guido van Rossumec22c921996-02-25 04:50:29 +00003142#endif /* GENERATINGCFM */
3143#endif /* macintosh */