blob: c946f88c0faadeea2b8884c0c269db2ebb5043e2 [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öwis25c7b502003-01-04 00:08:09 +0000745/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000746PyDoc_STRVAR(PyTclObject_string__doc__,
747"the string representation of this object, either as string or Unicode");
748
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000749static PyObject *
750PyTclObject_string(PyTclObject *self, void *ignored)
751{
752 char *s;
753 int i, len;
754 if (!self->string) {
755 s = Tcl_GetStringFromObj(self->value, &len);
756 for (i = 0; i < len; i++)
757 if (s[i] & 0x80)
758 break;
759#ifdef Py_USING_UNICODE
760 if (i == len)
761 /* It is an ASCII string. */
762 self->string = PyString_FromStringAndSize(s, len);
763 else {
764 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
765 if (!self->string) {
766 PyErr_Clear();
767 self->string = PyString_FromStringAndSize(s, len);
768 }
769 }
770#else
771 self->string = PyString_FromStringAndSize(s, len);
772#endif
773 if (!self->string)
774 return NULL;
775 }
776 Py_INCREF(self->string);
777 return self->string;
778}
779
780#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000781PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
782
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000783static PyObject *
784PyTclObject_unicode(PyTclObject *self, void *ignored)
785{
786 char *s;
787 int len;
788 if (self->string && PyUnicode_Check(self->string)) {
789 Py_INCREF(self->string);
790 return self->string;
791 }
792 /* XXX Could chache result if it is non-ASCII. */
793 s = Tcl_GetStringFromObj(self->value, &len);
794 return PyUnicode_DecodeUTF8(s, len, "strict");
795}
796#endif
797
Martin v. Löwisffad6332002-11-26 09:28:05 +0000798static PyObject *
799PyTclObject_repr(PyTclObject *self)
800{
801 char buf[50];
802 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
803 self->value->typePtr->name, (int)self->value);
804 return PyString_FromString(buf);
805}
806
Martin v. Löwis39195712003-01-04 00:33:13 +0000807PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
808
Martin v. Löwisffad6332002-11-26 09:28:05 +0000809static PyObject*
810get_typename(PyTclObject* obj, void* ignored)
811{
812 return PyString_FromString(obj->value->typePtr->name);
813}
814
Martin v. Löwis39195712003-01-04 00:33:13 +0000815
Martin v. Löwisffad6332002-11-26 09:28:05 +0000816static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000817 {"typename", (getter)get_typename, NULL, get_typename__doc__},
818 {"string", (getter)PyTclObject_string, NULL,
819 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000820 {0},
821};
822
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000823static PyMethodDef PyTclObject_methods[] = {
824 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000825 PyTclObject_unicode__doc__},
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000826 {0}
827};
828
Martin v. Löwisffad6332002-11-26 09:28:05 +0000829statichere PyTypeObject PyTclObject_Type = {
830 PyObject_HEAD_INIT(NULL)
831 0, /*ob_size*/
832 "_tkinter.Tcl_Obj", /*tp_name*/
833 sizeof(PyTclObject), /*tp_basicsize*/
834 0, /*tp_itemsize*/
835 /* methods */
836 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
837 0, /*tp_print*/
838 0, /*tp_getattr*/
839 0, /*tp_setattr*/
840 0, /*tp_compare*/
841 (reprfunc)PyTclObject_repr, /*tp_repr*/
842 0, /*tp_as_number*/
843 0, /*tp_as_sequence*/
844 0, /*tp_as_mapping*/
845 0, /*tp_hash*/
846 0, /*tp_call*/
847 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000848 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000849 0, /*tp_setattro*/
850 0, /*tp_as_buffer*/
851 Py_TPFLAGS_DEFAULT, /*tp_flags*/
852 0, /*tp_doc*/
853 0, /*tp_traverse*/
854 0, /*tp_clear*/
855 0, /*tp_richcompare*/
856 0, /*tp_weaklistoffset*/
857 0, /*tp_iter*/
858 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000859 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000860 0, /*tp_members*/
861 PyTclObject_getsetlist, /*tp_getset*/
862 0, /*tp_base*/
863 0, /*tp_dict*/
864 0, /*tp_descr_get*/
865 0, /*tp_descr_set*/
866 0, /*tp_dictoffset*/
867 0, /*tp_init*/
868 0, /*tp_alloc*/
869 0, /*tp_new*/
870 0, /*tp_free*/
871 0, /*tp_is_gc*/
872};
873
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000874static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000875AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000876{
877 Tcl_Obj *result;
878
879 if (PyString_Check(value))
880 return Tcl_NewStringObj(PyString_AS_STRING(value),
881 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000882 else if (PyBool_Check(value))
883 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000884 else if (PyInt_Check(value))
885 return Tcl_NewLongObj(PyInt_AS_LONG(value));
886 else if (PyFloat_Check(value))
887 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
888 else if (PyTuple_Check(value)) {
889 Tcl_Obj **argv = (Tcl_Obj**)
890 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
891 int i;
892 if(!argv)
893 return 0;
894 for(i=0;i<PyTuple_Size(value);i++)
895 argv[i] = AsObj(PyTuple_GetItem(value,i));
896 result = Tcl_NewListObj(PyTuple_Size(value), argv);
897 ckfree(FREECAST argv);
898 return result;
899 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000900#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000901 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000902 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
903 int size = PyUnicode_GET_SIZE(value);
904 /* This #ifdef assumes that Tcl uses UCS-2.
905 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000906#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000907 Tcl_UniChar *outbuf;
908 int i;
909 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
910 if (!outbuf) {
911 PyErr_NoMemory();
912 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000913 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000914 for (i = 0; i < size; i++) {
915 if (inbuf[i] >= 0x10000) {
916 /* Tcl doesn't do UTF-16, yet. */
917 PyErr_SetString(PyExc_ValueError,
918 "unsupported character");
919 ckfree(FREECAST outbuf);
920 return NULL;
921 }
922 outbuf[i] = inbuf[i];
923 }
924 result = Tcl_NewUnicodeObj(outbuf, size);
925 ckfree(FREECAST outbuf);
926 return result;
927#else
928 return Tcl_NewUnicodeObj(inbuf, size);
929#endif
930
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000931 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000932#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000933 else if(PyTclObject_Check(value)) {
934 Tcl_Obj *v = ((PyTclObject*)value)->value;
935 Tcl_IncrRefCount(v);
936 return v;
937 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000938 else {
939 PyObject *v = PyObject_Str(value);
940 if (!v)
941 return 0;
942 result = AsObj(v);
943 Py_DECREF(v);
944 return result;
945 }
946}
947
Martin v. Löwisffad6332002-11-26 09:28:05 +0000948static PyObject*
949FromObj(PyObject* tkapp, Tcl_Obj *value)
950{
951 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000952 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000953
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000954 if (value->typePtr == NULL) {
955 /* If the result contains any bytes with the top bit set,
956 it's UTF-8 and we should decode it to Unicode */
957#ifdef Py_USING_UNICODE
958 int i;
959 char *s = value->bytes;
960 int len = value->length;
961 for (i = 0; i < len; i++) {
962 if (value->bytes[i] & 0x80)
963 break;
964 }
965
966 if (i == value->length)
967 result = PyString_FromStringAndSize(s, len);
968 else {
969 /* Convert UTF-8 to Unicode string */
970 result = PyUnicode_DecodeUTF8(s, len, "strict");
971 if (result == NULL) {
972 PyErr_Clear();
973 result = PyString_FromStringAndSize(s, len);
974 }
975 }
976#else
977 res = PyString_FromStringAndSize(value->bytes, value->length);
978#endif
979 return result;
980 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000981
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000982 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000983 result = value->internalRep.longValue ? Py_True : Py_False;
984 Py_INCREF(result);
985 return result;
986 }
987
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000988 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000989 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000990 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000991 return PyString_FromStringAndSize(data, size);
992 }
993
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000994 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000995 return PyFloat_FromDouble(value->internalRep.doubleValue);
996 }
997
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000998 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000999 return PyInt_FromLong(value->internalRep.longValue);
1000 }
1001
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001002 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001003 int size;
1004 int i, status;
1005 PyObject *elem;
1006 Tcl_Obj *tcl_elem;
1007
1008 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1009 if (status == TCL_ERROR)
1010 return Tkinter_Error(tkapp);
1011 result = PyTuple_New(size);
1012 if (!result)
1013 return NULL;
1014 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001015 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001016 value, i, &tcl_elem);
1017 if (status == TCL_ERROR) {
1018 Py_DECREF(result);
1019 return Tkinter_Error(tkapp);
1020 }
1021 elem = FromObj(tkapp, tcl_elem);
1022 if (!elem) {
1023 Py_DECREF(result);
1024 return NULL;
1025 }
1026 PyTuple_SetItem(result, i, elem);
1027 }
1028 return result;
1029 }
1030
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001031 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001032 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001033 }
1034
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001035 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001036#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001037#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001038 PyObject *result;
1039 int size;
1040 Tcl_UniChar *input;
1041 Py_UNICODE *output;
1042
1043 size = Tcl_GetCharLength(value);
1044 result = PyUnicode_FromUnicode(NULL, size);
1045 if (!result)
1046 return NULL;
1047 input = Tcl_GetUnicode(value);
1048 output = PyUnicode_AS_UNICODE(result);
1049 while (size--)
1050 *output++ = *input++;
1051 return result;
1052#else
1053 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1054 Tcl_GetCharLength(value));
1055#endif
1056#else
1057 int size;
1058 char *c;
1059 c = Tcl_GetStringFromObj(value, &size);
1060 return PyString_FromStringAndSize(c, size);
1061#endif
1062 }
1063
1064 return newPyTclObject(value);
1065}
1066
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001067/* This mutex synchronizes inter-thread command calls. */
1068
1069TCL_DECLARE_MUTEX(call_mutex)
1070
1071typedef struct Tkapp_CallEvent {
1072 Tcl_Event ev; /* Must be first */
1073 TkappObject *self;
1074 PyObject *args;
1075 int flags;
1076 PyObject **res;
1077 PyObject **exc_type, **exc_value, **exc_tb;
1078 Tcl_Condition done;
1079} Tkapp_CallEvent;
1080
1081void
1082Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001083{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001084 int i;
1085 for (i = 0; i < objc; i++)
1086 Tcl_DecrRefCount(objv[i]);
1087 if (objv != objStore)
1088 ckfree(FREECAST objv);
1089}
Guido van Rossum18468821994-06-20 07:49:28 +00001090
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001091/* Convert Python objects to Tcl objects. This must happen in the
1092 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001093
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001094static Tcl_Obj**
1095Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1096{
1097 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001098 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001099 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001100 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001101
Guido van Rossum212643f1998-04-29 16:22:14 +00001102 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001103 objv[0] = AsObj(args);
1104 if (objv[0] == 0)
1105 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001106 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001107 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001108 }
1109 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001110 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001111
Guido van Rossum632de272000-03-29 00:19:50 +00001112 if (objc > ARGSZ) {
1113 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1114 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001115 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001116 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001117 goto finally;
1118 }
1119 }
1120
Guido van Rossum632de272000-03-29 00:19:50 +00001121 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001122 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001123 if (v == Py_None) {
1124 objc = i;
1125 break;
1126 }
Guido van Rossum632de272000-03-29 00:19:50 +00001127 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001128 if (!objv[i]) {
1129 /* Reset objc, so it attempts to clear
1130 objects only up to i. */
1131 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001132 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001133 }
Guido van Rossum632de272000-03-29 00:19:50 +00001134 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001135 }
1136 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001137 *pobjc = objc;
1138 return objv;
1139finally:
1140 Tkapp_CallDeallocArgs(objv, objStore, objc);
1141 return NULL;
1142}
Guido van Rossum212643f1998-04-29 16:22:14 +00001143
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001144/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001145
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001146static PyObject*
1147Tkapp_CallResult(TkappObject *self)
1148{
1149 PyObject *res = NULL;
1150 if(self->wantobjects) {
1151 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001152 /* Not sure whether the IncrRef is necessary, but something
1153 may overwrite the interpreter result while we are
1154 converting it. */
1155 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001156 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001157 Tcl_DecrRefCount(value);
1158 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001159 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001160 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001161
Guido van Rossum990f5c62000-05-04 15:07:16 +00001162 /* If the result contains any bytes with the top bit set,
1163 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001164#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001165 while (*p != '\0') {
1166 if (*p & 0x80)
1167 break;
1168 p++;
1169 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001170
Guido van Rossum990f5c62000-05-04 15:07:16 +00001171 if (*p == '\0')
1172 res = PyString_FromStringAndSize(s, (int)(p-s));
1173 else {
1174 /* Convert UTF-8 to Unicode string */
1175 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001176 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1177 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001178 PyErr_Clear();
1179 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001180 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001181 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001182#else
1183 p = strchr(p, '\0');
1184 res = PyString_FromStringAndSize(s, (int)(p-s));
1185#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001186 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001187 return res;
1188}
Guido van Rossum632de272000-03-29 00:19:50 +00001189
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001190/* Tkapp_CallProc is the event procedure that is executed in the context of
1191 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1192 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001193
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001194static int
1195Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1196{
1197 Tcl_Obj *objStore[ARGSZ];
1198 Tcl_Obj **objv;
1199 int objc;
1200 int i;
1201 ENTER_PYTHON
1202 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1203 if (!objv) {
1204 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1205 *(e->res) = NULL;
1206 }
1207 LEAVE_PYTHON
1208 if (!objv)
1209 goto done;
1210 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1211 ENTER_PYTHON
1212 if (i == TCL_ERROR) {
1213 *(e->res) = NULL;
1214 *(e->exc_type) = NULL;
1215 *(e->exc_tb) = NULL;
1216 *(e->exc_value) = PyObject_CallFunction(
1217 Tkinter_TclError, "s",
1218 Tcl_GetStringResult(e->self->interp));
1219 }
1220 else {
1221 *(e->res) = Tkapp_CallResult(e->self);
1222 }
1223 LEAVE_PYTHON
1224 done:
1225 /* Wake up calling thread. */
1226 Tcl_MutexLock(&call_mutex);
1227 Tcl_ConditionNotify(&e->done);
1228 Tcl_MutexUnlock(&call_mutex);
1229 return 1;
1230}
1231
1232/* This is the main entry point for calling a Tcl command.
1233 It supports three cases, with regard to threading:
1234 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1235 the context of the calling thread.
1236 2. Tcl is threaded, caller of the command is in the interpreter thread:
1237 Execute the command in the calling thread. Since the Tcl lock will
1238 not be used, we can merge that with case 1.
1239 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1240 the interpreter thread. Allocation of Tcl objects needs to occur in the
1241 interpreter thread, so we ship the PyObject* args to the target thread,
1242 and perform processing there. */
1243
1244static PyObject *
1245Tkapp_Call(PyObject *_self, PyObject *args)
1246{
1247 Tcl_Obj *objStore[ARGSZ];
1248 Tcl_Obj **objv = NULL;
1249 int objc, i;
1250 PyObject *res = NULL;
1251 TkappObject *self = (TkappObject*)_self;
1252 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1253 int flags = TCL_EVAL_DIRECT;
1254
Martin v. Löwisa9656492003-03-30 08:44:58 +00001255#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001256 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1257 /* We cannot call the command directly. Instead, we must
1258 marshal the parameters to the interpreter thread. */
1259 Tkapp_CallEvent *ev;
1260 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001261 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001262 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001263 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1264 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1265 ev->self = self;
1266 ev->args = args;
1267 ev->res = &res;
1268 ev->exc_type = &exc_type;
1269 ev->exc_value = &exc_value;
1270 ev->exc_tb = &exc_tb;
1271 ev->done = (Tcl_Condition)0;
1272
1273 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1274
1275 if (res == NULL) {
1276 if (exc_type)
1277 PyErr_Restore(exc_type, exc_value, exc_tb);
1278 else
1279 PyErr_SetObject(Tkinter_TclError, exc_value);
1280 }
1281 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001282 else
1283#endif
1284 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001285
1286 objv = Tkapp_CallArgs(args, objStore, &objc);
1287 if (!objv)
1288 return NULL;
1289
1290 ENTER_TCL
1291
1292 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1293
1294 ENTER_OVERLAP
1295
1296 if (i == TCL_ERROR)
1297 Tkinter_Error(_self);
1298 else
1299 res = Tkapp_CallResult(self);
1300
1301 LEAVE_OVERLAP_TCL
1302
1303 Tkapp_CallDeallocArgs(objv, objStore, objc);
1304 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001305 return res;
1306}
1307
1308
1309static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001310Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001311{
Guido van Rossum212643f1998-04-29 16:22:14 +00001312 /* Could do the same here as for Tkapp_Call(), but this is not used
1313 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1314 way for the user to do what all its Global* variants do (save and
1315 reset the scope pointer, call the local version, restore the saved
1316 scope pointer). */
1317
Guido van Rossum62320c91998-06-15 04:36:09 +00001318 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001319 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001320
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001321 CHECK_TCL_APPARTMENT;
1322
Guido van Rossum62320c91998-06-15 04:36:09 +00001323 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001324 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001325 int err;
1326 ENTER_TCL
1327 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001328 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001329 if (err == TCL_ERROR)
1330 res = Tkinter_Error(self);
1331 else
1332 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001333 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001334 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001335 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001336
1337 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001338}
1339
1340static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001341Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001342{
Barry Warsawfa701a81997-01-16 00:15:11 +00001343 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001344 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001345 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001346
Guido van Rossum43713e52000-02-29 13:59:29 +00001347 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001348 return NULL;
1349
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001350 CHECK_TCL_APPARTMENT;
1351
Guido van Rossum00d93061998-05-28 23:06:38 +00001352 ENTER_TCL
1353 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001354 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001355 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001356 res = Tkinter_Error(self);
1357 else
1358 res = PyString_FromString(Tkapp_Result(self));
1359 LEAVE_OVERLAP_TCL
1360 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001361}
1362
1363static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001364Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001365{
Barry Warsawfa701a81997-01-16 00:15:11 +00001366 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001367 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001368 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001369
Guido van Rossum43713e52000-02-29 13:59:29 +00001370 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001371 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001372
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001373 CHECK_TCL_APPARTMENT;
1374
Guido van Rossum00d93061998-05-28 23:06:38 +00001375 ENTER_TCL
1376 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001377 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001378 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001379 res = Tkinter_Error(self);
1380 else
1381 res = PyString_FromString(Tkapp_Result(self));
1382 LEAVE_OVERLAP_TCL
1383 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001384}
1385
1386static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001387Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001388{
Barry Warsawfa701a81997-01-16 00:15:11 +00001389 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001390 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001391 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001392
Guido van Rossum43713e52000-02-29 13:59:29 +00001393 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001394 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001395
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001396 CHECK_TCL_APPARTMENT;
1397
Guido van Rossum00d93061998-05-28 23:06:38 +00001398 ENTER_TCL
1399 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001400 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001401 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001402 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001403
Guido van Rossum62320c91998-06-15 04:36:09 +00001404 else
1405 res = PyString_FromString(Tkapp_Result(self));
1406 LEAVE_OVERLAP_TCL
1407 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001408}
1409
1410static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001411Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001412{
Barry Warsawfa701a81997-01-16 00:15:11 +00001413 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001414 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001415 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001416
Guido van Rossum35d43371997-08-02 00:09:09 +00001417 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001418 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001419
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001420 CHECK_TCL_APPARTMENT;
1421
Guido van Rossum00d93061998-05-28 23:06:38 +00001422 ENTER_TCL
1423 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001424 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001425 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001426 res = Tkinter_Error(self);
1427 else
1428 res = PyString_FromString(Tkapp_Result(self));
1429 LEAVE_OVERLAP_TCL
1430 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001431}
1432
1433static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001434Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001435{
Barry Warsawfa701a81997-01-16 00:15:11 +00001436 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001437
Guido van Rossum43713e52000-02-29 13:59:29 +00001438 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001439 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001440 CHECK_TCL_APPARTMENT;
1441
Guido van Rossum00d93061998-05-28 23:06:38 +00001442 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001443 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001444 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001445
Barry Warsawfa701a81997-01-16 00:15:11 +00001446 Py_INCREF(Py_None);
1447 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001448}
1449
Barry Warsawfa701a81997-01-16 00:15:11 +00001450
1451
Guido van Rossum18468821994-06-20 07:49:28 +00001452/** Tcl Variable **/
1453
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001454TCL_DECLARE_MUTEX(var_mutex)
1455
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001456typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001457typedef struct VarEvent {
1458 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001459 PyObject *self;
1460 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001461 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001462 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001463 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001464 PyObject **exc_type;
1465 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001466 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001467} VarEvent;
1468
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001469void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001470var_perform(VarEvent *ev)
1471{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001472 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1473 if (!*(ev->res)) {
1474 PyObject *exc, *val, *tb;
1475 PyErr_Fetch(&exc, &val, &tb);
1476 PyErr_NormalizeException(&exc, &val, &tb);
1477 *(ev->exc_type) = exc;
1478 *(ev->exc_val) = val;
1479 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001480 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001481
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001482}
1483
1484static int
1485var_proc(VarEvent* ev, int flags)
1486{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001487 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001488 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001489 Tcl_MutexLock(&var_mutex);
1490 Tcl_ConditionNotify(&ev->cond);
1491 Tcl_MutexUnlock(&var_mutex);
1492 LEAVE_PYTHON
1493 return 1;
1494}
1495
1496static PyObject*
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001497var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001498{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001499 TkappObject *self = (TkappObject*)_self;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001500#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001501 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001502 TkappObject *self = (TkappObject*)_self;
1503 VarEvent *ev;
1504 PyObject *res, *exc_type, *exc_val;
1505
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001506 /* The current thread is not the interpreter thread. Marshal
1507 the call to the interpreter thread, then wait for
1508 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001509 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001510 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001511
1512 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1513
1514 ev->self = _self;
1515 ev->args = args;
1516 ev->flags = flags;
1517 ev->func = func;
1518 ev->res = &res;
1519 ev->exc_type = &exc_type;
1520 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001521 ev->cond = NULL;
1522 ev->ev.proc = (Tcl_EventProc*)var_proc;
1523 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001524 if (!res) {
1525 PyErr_SetObject(exc_type, exc_val);
1526 Py_DECREF(exc_type);
1527 Py_DECREF(exc_val);
1528 return NULL;
1529 }
1530 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001531 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001532#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001533 /* Tcl is not threaded, or this is the interpreter thread. */
1534 return func(_self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001535}
1536
Guido van Rossum18468821994-06-20 07:49:28 +00001537static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001538SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001539{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001540 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001541 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001542 PyObject *res = NULL;
1543 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001544
Guido van Rossum43713e52000-02-29 13:59:29 +00001545 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001546 /* XXX Acquire tcl lock??? */
1547 newval = AsObj(newValue);
1548 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001549 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001550 ENTER_TCL
1551 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1552 newval, flags);
1553 ENTER_OVERLAP
1554 if (!ok)
1555 Tkinter_Error(self);
1556 else {
1557 res = Py_None;
1558 Py_INCREF(res);
1559 }
1560 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001561 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001562 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001563 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001564 if (PyArg_ParseTuple(args, "ssO:setvar",
1565 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001566 /* XXX must hold tcl lock already??? */
1567 newval = AsObj(newValue);
1568 ENTER_TCL
1569 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1570 ENTER_OVERLAP
1571 if (!ok)
1572 Tkinter_Error(self);
1573 else {
1574 res = Py_None;
1575 Py_INCREF(res);
1576 }
1577 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001578 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001579 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001580 return NULL;
1581 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001582 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001583 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001584}
1585
1586static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001587Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001588{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001589 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001590}
1591
1592static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001593Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001594{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001595 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001596}
1597
Barry Warsawfa701a81997-01-16 00:15:11 +00001598
1599
Guido van Rossum18468821994-06-20 07:49:28 +00001600static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001601GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001602{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001603 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001604 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001605 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001606
Guido van Rossum43713e52000-02-29 13:59:29 +00001607 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001608 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001609
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001610 ENTER_TCL
1611 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1612 ENTER_OVERLAP
1613 res = FromObj(self, tres);
1614 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001615 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001616}
1617
1618static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001619Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001620{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001621 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001622}
1623
1624static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001625Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001626{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001627 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001628}
1629
Barry Warsawfa701a81997-01-16 00:15:11 +00001630
1631
Guido van Rossum18468821994-06-20 07:49:28 +00001632static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001633UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001634{
Guido van Rossum35d43371997-08-02 00:09:09 +00001635 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001636 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001637 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001638
Guido van Rossum43713e52000-02-29 13:59:29 +00001639 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001640 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001641
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001642 ENTER_TCL
1643 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1644 ENTER_OVERLAP
1645 if (code == TCL_ERROR)
1646 res = Tkinter_Error(self);
1647 else {
1648 Py_INCREF(Py_None);
1649 res = Py_None;
1650 }
1651 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001652 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001653}
1654
1655static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001656Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001657{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001658 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001659}
1660
1661static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001662Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001663{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001664 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001665}
1666
Barry Warsawfa701a81997-01-16 00:15:11 +00001667
1668
Guido van Rossum18468821994-06-20 07:49:28 +00001669/** Tcl to Python **/
1670
1671static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001672Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001673{
Barry Warsawfa701a81997-01-16 00:15:11 +00001674 char *s;
1675 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001676
Martin v. Löwisffad6332002-11-26 09:28:05 +00001677 if (PyTuple_Size(args) == 1) {
1678 PyObject* o = PyTuple_GetItem(args, 0);
1679 if (PyInt_Check(o)) {
1680 Py_INCREF(o);
1681 return o;
1682 }
1683 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001684 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001685 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001686 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001687 return Tkinter_Error(self);
1688 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001689}
1690
1691static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001692Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001693{
Barry Warsawfa701a81997-01-16 00:15:11 +00001694 char *s;
1695 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001696
Martin v. Löwisffad6332002-11-26 09:28:05 +00001697 if (PyTuple_Size(args) == 1) {
1698 PyObject *o = PyTuple_GetItem(args, 0);
1699 if (PyFloat_Check(o)) {
1700 Py_INCREF(o);
1701 return o;
1702 }
1703 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001704 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001705 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001706 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001707 return Tkinter_Error(self);
1708 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001709}
1710
1711static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001712Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001713{
Barry Warsawfa701a81997-01-16 00:15:11 +00001714 char *s;
1715 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001716
Martin v. Löwisffad6332002-11-26 09:28:05 +00001717 if (PyTuple_Size(args) == 1) {
1718 PyObject *o = PyTuple_GetItem(args, 0);
1719 if (PyInt_Check(o)) {
1720 Py_INCREF(o);
1721 return o;
1722 }
1723 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001724 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001725 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001726 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1727 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001728 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001729}
1730
1731static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001732Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001733{
Barry Warsawfa701a81997-01-16 00:15:11 +00001734 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001735 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001736 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001737
Guido van Rossum43713e52000-02-29 13:59:29 +00001738 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001739 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001740
1741 CHECK_TCL_APPARTMENT;
1742
Guido van Rossum00d93061998-05-28 23:06:38 +00001743 ENTER_TCL
1744 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001745 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001746 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001747 res = Tkinter_Error(self);
1748 else
1749 res = Py_BuildValue("s", Tkapp_Result(self));
1750 LEAVE_OVERLAP_TCL
1751 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001752}
1753
1754static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001755Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001756{
Barry Warsawfa701a81997-01-16 00:15:11 +00001757 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001758 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001759 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001760 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001761
Guido van Rossum43713e52000-02-29 13:59:29 +00001762 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001763 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001764
1765 CHECK_TCL_APPARTMENT;
1766
Guido van Rossum00d93061998-05-28 23:06:38 +00001767 ENTER_TCL
1768 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001769 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001770 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001771 res = Tkinter_Error(self);
1772 else
1773 res = Py_BuildValue("l", v);
1774 LEAVE_OVERLAP_TCL
1775 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001776}
1777
1778static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001779Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001780{
Barry Warsawfa701a81997-01-16 00:15:11 +00001781 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001782 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001783 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001784 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001785
Guido van Rossum43713e52000-02-29 13:59:29 +00001786 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001787 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001788 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001789 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001790 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001791 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001792 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001793 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001794 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001795 res = Tkinter_Error(self);
1796 else
1797 res = Py_BuildValue("d", v);
1798 LEAVE_OVERLAP_TCL
1799 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001800}
1801
1802static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001803Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001804{
Barry Warsawfa701a81997-01-16 00:15:11 +00001805 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001806 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001807 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001808 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001809
Guido van Rossum43713e52000-02-29 13:59:29 +00001810 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001811 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001812 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001813 ENTER_TCL
1814 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001815 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001816 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001817 res = Tkinter_Error(self);
1818 else
1819 res = Py_BuildValue("i", v);
1820 LEAVE_OVERLAP_TCL
1821 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001822}
1823
Barry Warsawfa701a81997-01-16 00:15:11 +00001824
1825
Guido van Rossum18468821994-06-20 07:49:28 +00001826static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001827Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001828{
Barry Warsawfa701a81997-01-16 00:15:11 +00001829 char *list;
1830 int argc;
1831 char **argv;
1832 PyObject *v;
1833 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001834
Martin v. Löwisffad6332002-11-26 09:28:05 +00001835 if (PyTuple_Size(args) == 1) {
1836 v = PyTuple_GetItem(args, 0);
1837 if (PyTuple_Check(v)) {
1838 Py_INCREF(v);
1839 return v;
1840 }
1841 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001842 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001843 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001844
Barry Warsawfa701a81997-01-16 00:15:11 +00001845 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1846 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001847
Barry Warsawfa701a81997-01-16 00:15:11 +00001848 if (!(v = PyTuple_New(argc)))
1849 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001850
Barry Warsawfa701a81997-01-16 00:15:11 +00001851 for (i = 0; i < argc; i++) {
1852 PyObject *s = PyString_FromString(argv[i]);
1853 if (!s || PyTuple_SetItem(v, i, s)) {
1854 Py_DECREF(v);
1855 v = NULL;
1856 goto finally;
1857 }
1858 }
Guido van Rossum18468821994-06-20 07:49:28 +00001859
Barry Warsawfa701a81997-01-16 00:15:11 +00001860 finally:
1861 ckfree(FREECAST argv);
1862 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001863}
1864
1865static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001866Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001867{
Barry Warsawfa701a81997-01-16 00:15:11 +00001868 char *list;
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 PyObject* o = PyTuple_GetItem(args, 0);
1872 if (PyTuple_Check(o)) {
1873 o = SplitObj(o);
1874 return o;
1875 }
1876 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001877 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001878 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001879 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001880}
1881
1882static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001883Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001884{
Barry Warsawfa701a81997-01-16 00:15:11 +00001885 char *s = Merge(args);
1886 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001887
Barry Warsawfa701a81997-01-16 00:15:11 +00001888 if (s) {
1889 res = PyString_FromString(s);
1890 ckfree(s);
1891 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001892
1893 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001894}
1895
Barry Warsawfa701a81997-01-16 00:15:11 +00001896
1897
Guido van Rossum18468821994-06-20 07:49:28 +00001898/** Tcl Command **/
1899
Guido van Rossum00d93061998-05-28 23:06:38 +00001900/* Client data struct */
1901typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001902 PyObject *self;
1903 PyObject *func;
1904} PythonCmd_ClientData;
1905
1906static int
Fred Drake509d79a2000-07-08 04:04:38 +00001907PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001908{
1909 errorInCmd = 1;
1910 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1911 LEAVE_PYTHON
1912 return TCL_ERROR;
1913}
1914
Guido van Rossum18468821994-06-20 07:49:28 +00001915/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001916 * function or method.
1917 */
Guido van Rossum18468821994-06-20 07:49:28 +00001918static int
Fred Drake509d79a2000-07-08 04:04:38 +00001919PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001920{
Guido van Rossum00d93061998-05-28 23:06:38 +00001921 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001922 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001923 int i, rv;
1924 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001925
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001926 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001927
Barry Warsawfa701a81997-01-16 00:15:11 +00001928 /* TBD: no error checking here since we know, via the
1929 * Tkapp_CreateCommand() that the client data is a two-tuple
1930 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001931 self = data->self;
1932 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001933
Barry Warsawfa701a81997-01-16 00:15:11 +00001934 /* Create argument list (argv1, ..., argvN) */
1935 if (!(arg = PyTuple_New(argc - 1)))
1936 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001937
Barry Warsawfa701a81997-01-16 00:15:11 +00001938 for (i = 0; i < (argc - 1); i++) {
1939 PyObject *s = PyString_FromString(argv[i + 1]);
1940 if (!s || PyTuple_SetItem(arg, i, s)) {
1941 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001942 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001943 }
1944 }
1945 res = PyEval_CallObject(func, arg);
1946 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001947
Barry Warsawfa701a81997-01-16 00:15:11 +00001948 if (res == NULL)
1949 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001950
Barry Warsawfa701a81997-01-16 00:15:11 +00001951 if (!(tmp = PyList_New(0))) {
1952 Py_DECREF(res);
1953 return PythonCmd_Error(interp);
1954 }
1955
Guido van Rossum2834b972000-10-06 16:58:26 +00001956 s = AsString(res, tmp);
1957 if (s == NULL) {
1958 rv = PythonCmd_Error(interp);
1959 }
1960 else {
1961 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1962 rv = TCL_OK;
1963 }
1964
Barry Warsawfa701a81997-01-16 00:15:11 +00001965 Py_DECREF(res);
1966 Py_DECREF(tmp);
1967
Guido van Rossum00d93061998-05-28 23:06:38 +00001968 LEAVE_PYTHON
1969
Guido van Rossum2834b972000-10-06 16:58:26 +00001970 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001971}
1972
1973static void
Fred Drake509d79a2000-07-08 04:04:38 +00001974PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001975{
Guido van Rossum00d93061998-05-28 23:06:38 +00001976 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1977
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001978 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001979 Py_XDECREF(data->self);
1980 Py_XDECREF(data->func);
1981 PyMem_DEL(data);
1982 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001983}
1984
Barry Warsawfa701a81997-01-16 00:15:11 +00001985
1986
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001987
1988TCL_DECLARE_MUTEX(command_mutex)
1989
1990typedef struct CommandEvent{
1991 Tcl_Event ev;
1992 Tcl_Interp* interp;
1993 char *name;
1994 int create;
1995 int *status;
1996 ClientData *data;
1997 Tcl_Condition done;
1998} CommandEvent;
1999
2000static int
2001Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002002{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002003 if (ev->create)
2004 *ev->status = Tcl_CreateCommand(
2005 ev->interp, ev->name, PythonCmd,
2006 ev->data, PythonCmdDelete) == NULL;
2007 else
2008 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2009 Tcl_MutexLock(&command_mutex);
2010 Tcl_ConditionNotify(&ev->done);
2011 Tcl_MutexUnlock(&command_mutex);
2012 return 1;
2013}
2014
2015static PyObject *
2016Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2017{
2018 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002019 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002020 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002021 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002022 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002023
Guido van Rossum43713e52000-02-29 13:59:29 +00002024 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002025 return NULL;
2026 if (!PyCallable_Check(func)) {
2027 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002028 return NULL;
2029 }
Guido van Rossum18468821994-06-20 07:49:28 +00002030
Martin v. Löwisa9656492003-03-30 08:44:58 +00002031#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002032 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002033 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002034 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002035#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002036
Guido van Rossum00d93061998-05-28 23:06:38 +00002037 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002038 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002039 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002040 Py_XINCREF(self);
2041 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002042 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002043 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002044
2045 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2046 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2047 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2048 ev->interp = self->interp;
2049 ev->create = 1;
2050 ev->name = cmdName;
2051 ev->data = (ClientData)data;
2052 ev->status = &err;
2053 ev->done = NULL;
2054 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2055 }
2056 else {
2057 ENTER_TCL
2058 err = Tcl_CreateCommand(
2059 Tkapp_Interp(self), cmdName, PythonCmd,
2060 (ClientData)data, PythonCmdDelete) == NULL;
2061 LEAVE_TCL
2062 }
2063 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002064 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002065 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002066 return NULL;
2067 }
Guido van Rossum18468821994-06-20 07:49:28 +00002068
Barry Warsawfa701a81997-01-16 00:15:11 +00002069 Py_INCREF(Py_None);
2070 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002071}
2072
Barry Warsawfa701a81997-01-16 00:15:11 +00002073
2074
Guido van Rossum18468821994-06-20 07:49:28 +00002075static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002076Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002077{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002078 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002079 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002080 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002081
Guido van Rossum43713e52000-02-29 13:59:29 +00002082 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002083 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002084 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2085 CommandEvent *ev;
2086 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2087 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2088 ev->interp = self->interp;
2089 ev->create = 0;
2090 ev->name = cmdName;
2091 ev->status = &err;
2092 ev->done = NULL;
2093 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2094 &command_mutex);
2095 }
2096 else {
2097 ENTER_TCL
2098 err = Tcl_DeleteCommand(self->interp, cmdName);
2099 LEAVE_TCL
2100 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002101 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002102 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2103 return NULL;
2104 }
2105 Py_INCREF(Py_None);
2106 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002107}
2108
Barry Warsawfa701a81997-01-16 00:15:11 +00002109
2110
Guido van Rossum00d93061998-05-28 23:06:38 +00002111#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002112/** File Handler **/
2113
Guido van Rossum00d93061998-05-28 23:06:38 +00002114typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002115 PyObject *func;
2116 PyObject *file;
2117 int id;
2118 struct _fhcdata *next;
2119} FileHandler_ClientData;
2120
2121static FileHandler_ClientData *HeadFHCD;
2122
2123static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002124NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002125{
2126 FileHandler_ClientData *p;
2127 p = PyMem_NEW(FileHandler_ClientData, 1);
2128 if (p != NULL) {
2129 Py_XINCREF(func);
2130 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002131 p->func = func;
2132 p->file = file;
2133 p->id = id;
2134 p->next = HeadFHCD;
2135 HeadFHCD = p;
2136 }
2137 return p;
2138}
2139
2140static void
Fred Drake509d79a2000-07-08 04:04:38 +00002141DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002142{
2143 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002144
2145 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002146 while ((p = *pp) != NULL) {
2147 if (p->id == id) {
2148 *pp = p->next;
2149 Py_XDECREF(p->func);
2150 Py_XDECREF(p->file);
2151 PyMem_DEL(p);
2152 }
2153 else
2154 pp = &p->next;
2155 }
2156}
2157
Guido van Rossuma597dde1995-01-10 20:56:29 +00002158static void
Fred Drake509d79a2000-07-08 04:04:38 +00002159FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002160{
Guido van Rossum00d93061998-05-28 23:06:38 +00002161 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002162 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002163
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002164 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002165 func = data->func;
2166 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002167
Barry Warsawfa701a81997-01-16 00:15:11 +00002168 arg = Py_BuildValue("(Oi)", file, (long) mask);
2169 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002170 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002171
2172 if (res == NULL) {
2173 errorInCmd = 1;
2174 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2175 }
2176 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002177 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002178}
2179
Guido van Rossum18468821994-06-20 07:49:28 +00002180static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002181Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2182 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002183{
Guido van Rossum00d93061998-05-28 23:06:38 +00002184 FileHandler_ClientData *data;
2185 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002186 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002187
Guido van Rossum2834b972000-10-06 16:58:26 +00002188 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2189 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002190 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002191
Martin v. Löwisa9656492003-03-30 08:44:58 +00002192#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002193 if (!self && !tcl_lock) {
2194 /* We don't have the Tcl lock since Tcl is threaded. */
2195 PyErr_SetString(PyExc_RuntimeError,
2196 "_tkinter.createfilehandler not supported "
2197 "for threaded Tcl");
2198 return NULL;
2199 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002200#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002201
2202 if (self) {
2203 CHECK_TCL_APPARTMENT;
2204 }
2205
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002206 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002207 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002208 return NULL;
2209 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002210 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002211 return NULL;
2212 }
2213
Guido van Rossuma80649b2000-03-28 20:07:05 +00002214 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002215 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002216 return NULL;
2217
Barry Warsawfa701a81997-01-16 00:15:11 +00002218 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002219 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002220 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002221 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002222 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002223 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002224}
2225
2226static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002227Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002228{
Barry Warsawfa701a81997-01-16 00:15:11 +00002229 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002230 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002231
Guido van Rossum43713e52000-02-29 13:59:29 +00002232 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002233 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002234
Martin v. Löwisa9656492003-03-30 08:44:58 +00002235#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002236 if (!self && !tcl_lock) {
2237 /* We don't have the Tcl lock since Tcl is threaded. */
2238 PyErr_SetString(PyExc_RuntimeError,
2239 "_tkinter.deletefilehandler not supported "
2240 "for threaded Tcl");
2241 return NULL;
2242 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002243#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002244
2245 if (self) {
2246 CHECK_TCL_APPARTMENT;
2247 }
2248
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002249 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002250 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002251 return NULL;
2252
Guido van Rossuma80649b2000-03-28 20:07:05 +00002253 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002254
Barry Warsawfa701a81997-01-16 00:15:11 +00002255 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002256 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002257 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002258 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002259 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002260 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002261}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002262#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002263
Barry Warsawfa701a81997-01-16 00:15:11 +00002264
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002265/**** Tktt Object (timer token) ****/
2266
Jeremy Hylton938ace62002-07-17 16:30:39 +00002267static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002268
Guido van Rossum00d93061998-05-28 23:06:38 +00002269typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002270 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002271 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002272 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002273} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002274
2275static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002276Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002277{
Barry Warsawfa701a81997-01-16 00:15:11 +00002278 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002279 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002280
Guido van Rossum43713e52000-02-29 13:59:29 +00002281 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002282 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002283 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002284 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002285 v->token = NULL;
2286 }
2287 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002288 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002289 Py_DECREF(func);
2290 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002291 }
2292 Py_INCREF(Py_None);
2293 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002294}
2295
2296static PyMethodDef Tktt_methods[] =
2297{
Neal Norwitzb0493252002-03-31 14:44:22 +00002298 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002299 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002300};
2301
2302static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002303Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002304{
Barry Warsawfa701a81997-01-16 00:15:11 +00002305 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002306
Guido van Rossumb18618d2000-05-03 23:44:39 +00002307 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002308 if (v == NULL)
2309 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002310
Guido van Rossum00d93061998-05-28 23:06:38 +00002311 Py_INCREF(func);
2312 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002313 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002314
2315 /* Extra reference, deleted when called or when handler is deleted */
2316 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002317 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002318}
2319
2320static void
Fred Drake509d79a2000-07-08 04:04:38 +00002321Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002322{
Guido van Rossum00d93061998-05-28 23:06:38 +00002323 TkttObject *v = (TkttObject *)self;
2324 PyObject *func = v->func;
2325
2326 Py_XDECREF(func);
2327
Guido van Rossumb18618d2000-05-03 23:44:39 +00002328 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002329}
2330
Guido van Rossum597ac201998-05-12 14:36:19 +00002331static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002332Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002333{
Barry Warsawfa701a81997-01-16 00:15:11 +00002334 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002335 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002336
Tim Peters885d4572001-11-28 20:27:42 +00002337 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002338 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002339 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002340}
2341
2342static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002343Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002344{
Barry Warsawfa701a81997-01-16 00:15:11 +00002345 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002346}
2347
2348static PyTypeObject Tktt_Type =
2349{
Guido van Rossum35d43371997-08-02 00:09:09 +00002350 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002351 0, /*ob_size */
2352 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002353 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002354 0, /*tp_itemsize */
2355 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002356 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002357 Tktt_GetAttr, /*tp_getattr */
2358 0, /*tp_setattr */
2359 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002360 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002361 0, /*tp_as_number */
2362 0, /*tp_as_sequence */
2363 0, /*tp_as_mapping */
2364 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002365};
2366
Barry Warsawfa701a81997-01-16 00:15:11 +00002367
2368
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002369/** Timer Handler **/
2370
2371static void
Fred Drake509d79a2000-07-08 04:04:38 +00002372TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002373{
Guido van Rossum00d93061998-05-28 23:06:38 +00002374 TkttObject *v = (TkttObject *)clientData;
2375 PyObject *func = v->func;
2376 PyObject *res;
2377
2378 if (func == NULL)
2379 return;
2380
2381 v->func = NULL;
2382
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002383 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002384
2385 res = PyEval_CallObject(func, NULL);
2386 Py_DECREF(func);
2387 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002388
Barry Warsawfa701a81997-01-16 00:15:11 +00002389 if (res == NULL) {
2390 errorInCmd = 1;
2391 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2392 }
2393 else
2394 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002395
2396 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002397}
2398
2399static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002400Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002401{
Barry Warsawfa701a81997-01-16 00:15:11 +00002402 int milliseconds;
2403 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002404 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002405
Guido van Rossum2834b972000-10-06 16:58:26 +00002406 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2407 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002408 return NULL;
2409 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002410 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002411 return NULL;
2412 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002413
Martin v. Löwisa9656492003-03-30 08:44:58 +00002414#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002415 if (!self && !tcl_lock) {
2416 /* We don't have the Tcl lock since Tcl is threaded. */
2417 PyErr_SetString(PyExc_RuntimeError,
2418 "_tkinter.createtimerhandler not supported "
2419 "for threaded Tcl");
2420 return NULL;
2421 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002422#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002423
2424 if (self) {
2425 CHECK_TCL_APPARTMENT;
2426 }
2427
Guido van Rossum00d93061998-05-28 23:06:38 +00002428 v = Tktt_New(func);
2429 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2430 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002431
Guido van Rossum00d93061998-05-28 23:06:38 +00002432 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002433}
2434
Barry Warsawfa701a81997-01-16 00:15:11 +00002435
Guido van Rossum18468821994-06-20 07:49:28 +00002436/** Event Loop **/
2437
Guido van Rossum18468821994-06-20 07:49:28 +00002438static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002439Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002440{
Barry Warsawfa701a81997-01-16 00:15:11 +00002441 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002442 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002443#ifdef WITH_THREAD
2444 PyThreadState *tstate = PyThreadState_Get();
2445#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002446
Guido van Rossum43713e52000-02-29 13:59:29 +00002447 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002448 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002449
Martin v. Löwisa9656492003-03-30 08:44:58 +00002450#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002451 if (!self && !tcl_lock) {
2452 /* We don't have the Tcl lock since Tcl is threaded. */
2453 PyErr_SetString(PyExc_RuntimeError,
2454 "_tkinter.mainloop not supported "
2455 "for threaded Tcl");
2456 return NULL;
2457 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002458#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002459
2460 if (self) {
2461 CHECK_TCL_APPARTMENT;
2462 self->dispatching = 1;
2463 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002464
Barry Warsawfa701a81997-01-16 00:15:11 +00002465 quitMainLoop = 0;
2466 while (Tk_GetNumMainWindows() > threshold &&
2467 !quitMainLoop &&
2468 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002469 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002470 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002471
2472#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002473 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002474 /* Allow other Python threads to run. */
2475 ENTER_TCL
2476 result = Tcl_DoOneEvent(0);
2477 LEAVE_TCL
2478 }
2479 else {
2480 Py_BEGIN_ALLOW_THREADS
2481 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2482 tcl_tstate = tstate;
2483 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2484 tcl_tstate = NULL;
2485 if(tcl_lock)PyThread_release_lock(tcl_lock);
2486 if (result == 0)
2487 Sleep(20);
2488 Py_END_ALLOW_THREADS
2489 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002490#else
2491 result = Tcl_DoOneEvent(0);
2492#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002493
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002494 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002495 if (self)
2496 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002497 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002498 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002499 if (result < 0)
2500 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002501 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002502 if (self)
2503 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002504 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002505
Barry Warsawfa701a81997-01-16 00:15:11 +00002506 if (errorInCmd) {
2507 errorInCmd = 0;
2508 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2509 excInCmd = valInCmd = trbInCmd = NULL;
2510 return NULL;
2511 }
2512 Py_INCREF(Py_None);
2513 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002514}
2515
2516static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002517Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002518{
Guido van Rossum35d43371997-08-02 00:09:09 +00002519 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002520 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002521
Guido van Rossum43713e52000-02-29 13:59:29 +00002522 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002523 return NULL;
2524
Guido van Rossum00d93061998-05-28 23:06:38 +00002525 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002526 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002527 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002528 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002529}
2530
2531static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002532Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002533{
2534
Guido van Rossum43713e52000-02-29 13:59:29 +00002535 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002536 return NULL;
2537
2538 quitMainLoop = 1;
2539 Py_INCREF(Py_None);
2540 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002541}
2542
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002543static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002544Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002545{
2546
Guido van Rossum43713e52000-02-29 13:59:29 +00002547 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002548 return NULL;
2549
2550 return PyInt_FromLong((long)Tkapp_Interp(self));
2551}
2552
Barry Warsawfa701a81997-01-16 00:15:11 +00002553
Martin v. Löwisffad6332002-11-26 09:28:05 +00002554static PyObject *
2555Tkapp_WantObjects(PyObject *self, PyObject *args)
2556{
2557
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002558 int wantobjects;
2559 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002560 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002561 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002562
2563 Py_INCREF(Py_None);
2564 return Py_None;
2565}
2566
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002567static PyObject *
2568Tkapp_WillDispatch(PyObject *self, PyObject *args)
2569{
2570
2571 ((TkappObject*)self)->dispatching = 1;
2572
2573 Py_INCREF(Py_None);
2574 return Py_None;
2575}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002576
Barry Warsawfa701a81997-01-16 00:15:11 +00002577
Guido van Rossum18468821994-06-20 07:49:28 +00002578/**** Tkapp Method List ****/
2579
2580static PyMethodDef Tkapp_methods[] =
2581{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002582 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002583 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002584 {"call", Tkapp_Call, METH_OLDARGS},
2585 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2586 {"eval", Tkapp_Eval, METH_VARARGS},
2587 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2588 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2589 {"record", Tkapp_Record, METH_VARARGS},
2590 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2591 {"setvar", Tkapp_SetVar, METH_VARARGS},
2592 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2593 {"getvar", Tkapp_GetVar, METH_VARARGS},
2594 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2595 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2596 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2597 {"getint", Tkapp_GetInt, METH_VARARGS},
2598 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2599 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2600 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2601 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2602 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2603 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2604 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2605 {"split", Tkapp_Split, METH_VARARGS},
2606 {"merge", Tkapp_Merge, METH_OLDARGS},
2607 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2608 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002609#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002610 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2611 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002612#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002613 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2614 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2615 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2616 {"quit", Tkapp_Quit, METH_VARARGS},
2617 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002618 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002619};
2620
Barry Warsawfa701a81997-01-16 00:15:11 +00002621
2622
Guido van Rossum18468821994-06-20 07:49:28 +00002623/**** Tkapp Type Methods ****/
2624
2625static void
Fred Drake509d79a2000-07-08 04:04:38 +00002626Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002627{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002628 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002629 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002630 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002631 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002632 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002633 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002634}
2635
2636static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002637Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002638{
Guido van Rossum35d43371997-08-02 00:09:09 +00002639 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002640}
2641
2642static PyTypeObject Tkapp_Type =
2643{
Guido van Rossum35d43371997-08-02 00:09:09 +00002644 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002645 0, /*ob_size */
2646 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002647 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002648 0, /*tp_itemsize */
2649 Tkapp_Dealloc, /*tp_dealloc */
2650 0, /*tp_print */
2651 Tkapp_GetAttr, /*tp_getattr */
2652 0, /*tp_setattr */
2653 0, /*tp_compare */
2654 0, /*tp_repr */
2655 0, /*tp_as_number */
2656 0, /*tp_as_sequence */
2657 0, /*tp_as_mapping */
2658 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002659};
2660
Barry Warsawfa701a81997-01-16 00:15:11 +00002661
2662
Guido van Rossum18468821994-06-20 07:49:28 +00002663/**** Tkinter Module ****/
2664
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002665typedef struct {
2666 PyObject* tuple;
2667 int size; /* current size */
2668 int maxsize; /* allocated size */
2669} FlattenContext;
2670
2671static int
2672_bump(FlattenContext* context, int size)
2673{
Guido van Rossum2834b972000-10-06 16:58:26 +00002674 /* expand tuple to hold (at least) size new items.
2675 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002676
2677 int maxsize = context->maxsize * 2;
2678
2679 if (maxsize < context->size + size)
2680 maxsize = context->size + size;
2681
2682 context->maxsize = maxsize;
2683
Tim Peters4324aa32001-05-28 22:30:08 +00002684 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002685}
2686
2687static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002688_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002689{
2690 /* add tuple or list to argument tuple (recursively) */
2691
2692 int i, size;
2693
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002694 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002695 PyErr_SetString(PyExc_ValueError,
2696 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002697 return 0;
2698 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002699 size = PyList_GET_SIZE(item);
2700 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002701 if (context->size + size > context->maxsize &&
2702 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002703 return 0;
2704 /* copy items to output tuple */
2705 for (i = 0; i < size; i++) {
2706 PyObject *o = PyList_GET_ITEM(item, i);
2707 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002708 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002709 return 0;
2710 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002711 if (context->size + 1 > context->maxsize &&
2712 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002713 return 0;
2714 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002715 PyTuple_SET_ITEM(context->tuple,
2716 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002717 }
2718 }
2719 } else if (PyTuple_Check(item)) {
2720 /* same, for tuples */
2721 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002722 if (context->size + size > context->maxsize &&
2723 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002724 return 0;
2725 for (i = 0; i < size; i++) {
2726 PyObject *o = PyTuple_GET_ITEM(item, i);
2727 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002728 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002729 return 0;
2730 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002731 if (context->size + 1 > context->maxsize &&
2732 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002733 return 0;
2734 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002735 PyTuple_SET_ITEM(context->tuple,
2736 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002737 }
2738 }
2739 } else {
2740 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2741 return 0;
2742 }
2743 return 1;
2744}
2745
2746static PyObject *
2747Tkinter_Flatten(PyObject* self, PyObject* args)
2748{
2749 FlattenContext context;
2750 PyObject* item;
2751
2752 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2753 return NULL;
2754
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002755 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002756 if (context.maxsize <= 0)
2757 return PyTuple_New(0);
2758
2759 context.tuple = PyTuple_New(context.maxsize);
2760 if (!context.tuple)
2761 return NULL;
2762
2763 context.size = 0;
2764
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002765 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002766 return NULL;
2767
Tim Peters4324aa32001-05-28 22:30:08 +00002768 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002769 return NULL;
2770
2771 return context.tuple;
2772}
2773
Guido van Rossum18468821994-06-20 07:49:28 +00002774static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002775Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002776{
Barry Warsawfa701a81997-01-16 00:15:11 +00002777 char *screenName = NULL;
2778 char *baseName = NULL;
2779 char *className = NULL;
2780 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002781 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002782
Guido van Rossum35d43371997-08-02 00:09:09 +00002783 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002784 if (baseName != NULL)
2785 baseName++;
2786 else
2787 baseName = Py_GetProgramName();
2788 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002789
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002790 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002791 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002792 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002793 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002794
Barry Warsawfa701a81997-01-16 00:15:11 +00002795 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002796 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002797}
2798
2799static PyMethodDef moduleMethods[] =
2800{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002801 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2802 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002803#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002804 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2805 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002806#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002807 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2808 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2809 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2810 {"quit", Tkapp_Quit, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002811 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002812};
2813
Guido van Rossum7bf15641998-05-22 18:28:17 +00002814#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002815
2816static int stdin_ready = 0;
2817
Guido van Rossumad4db171998-06-13 13:56:28 +00002818#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002819static void
Fred Drake509d79a2000-07-08 04:04:38 +00002820MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002821{
2822 stdin_ready = 1;
2823}
Guido van Rossumad4db171998-06-13 13:56:28 +00002824#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002825
Martin v. Löwisa9656492003-03-30 08:44:58 +00002826#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002827static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002828#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002829
Guido van Rossum18468821994-06-20 07:49:28 +00002830static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002831EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002832{
Guido van Rossumad4db171998-06-13 13:56:28 +00002833#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002834 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002835#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002836#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002837 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002838#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002839 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002840 errorInCmd = 0;
2841#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002842 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002843 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002844#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002845 while (!errorInCmd && !stdin_ready) {
2846 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002847#ifdef MS_WINDOWS
2848 if (_kbhit()) {
2849 stdin_ready = 1;
2850 break;
2851 }
2852#endif
2853#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002854 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002855 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002856 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002857
Guido van Rossum00d93061998-05-28 23:06:38 +00002858 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002859
2860 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002861 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002862 if (result == 0)
2863 Sleep(20);
2864 Py_END_ALLOW_THREADS
2865#else
2866 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002867#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002868
2869 if (result < 0)
2870 break;
2871 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002872#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002873 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002874#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002875 if (errorInCmd) {
2876 errorInCmd = 0;
2877 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2878 excInCmd = valInCmd = trbInCmd = NULL;
2879 PyErr_Print();
2880 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002881#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002882 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002883#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002884 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002885}
Guido van Rossum18468821994-06-20 07:49:28 +00002886
Guido van Rossum00d93061998-05-28 23:06:38 +00002887#endif
2888
Guido van Rossum7bf15641998-05-22 18:28:17 +00002889static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002890EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002891{
Guido van Rossum00d93061998-05-28 23:06:38 +00002892#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002893 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002894#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002895 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002896#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002897 PyOS_InputHook = EventHook;
2898 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002899#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002900}
2901
2902static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002903DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002904{
Guido van Rossum00d93061998-05-28 23:06:38 +00002905#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002906 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2907 PyOS_InputHook = NULL;
2908 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002909#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002910}
2911
Barry Warsawfa701a81997-01-16 00:15:11 +00002912
2913/* all errors will be checked in one fell swoop in init_tkinter() */
2914static void
Fred Drake509d79a2000-07-08 04:04:38 +00002915ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002916{
2917 PyObject *v = PyInt_FromLong(val);
2918 if (v) {
2919 PyDict_SetItemString(d, name, v);
2920 Py_DECREF(v);
2921 }
2922}
2923static void
Fred Drake509d79a2000-07-08 04:04:38 +00002924ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002925{
2926 PyObject *v = PyString_FromString(val);
2927 if (v) {
2928 PyDict_SetItemString(d, name, v);
2929 Py_DECREF(v);
2930 }
2931}
2932
2933
Mark Hammond62b1ab12002-07-23 06:31:15 +00002934PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002935init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002936{
Barry Warsawfa701a81997-01-16 00:15:11 +00002937 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002938
Barry Warsawfa701a81997-01-16 00:15:11 +00002939 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002940
2941#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002942 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002943#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002944
Barry Warsawfa701a81997-01-16 00:15:11 +00002945 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002946
Barry Warsawfa701a81997-01-16 00:15:11 +00002947 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00002948 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00002949 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002950
Guido van Rossum35d43371997-08-02 00:09:09 +00002951 ins_long(d, "READABLE", TCL_READABLE);
2952 ins_long(d, "WRITABLE", TCL_WRITABLE);
2953 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2954 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2955 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2956 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2957 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2958 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2959 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002960 ins_string(d, "TK_VERSION", TK_VERSION);
2961 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002962
Guido van Rossum83551bf1997-09-13 00:44:23 +00002963 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002964
2965 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002966 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2967
Martin v. Löwisffad6332002-11-26 09:28:05 +00002968 PyTclObject_Type.ob_type = &PyType_Type;
2969 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002970
2971#ifdef TK_AQUA
2972 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2973 * start waking up. Note that Tcl_FindExecutable will do this, this
2974 * code must be above it! The original warning from
2975 * tkMacOSXAppInit.c is copied below.
2976 *
2977 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2978 * Tcl interpreter for now. It probably should work to do this
2979 * in the other order, but for now it doesn't seem to.
2980 *
2981 */
2982 Tk_MacOSXSetupTkNotifier();
2983#endif
2984
2985
Guido van Rossume187b0e2000-03-27 21:46:29 +00002986 /* This helps the dynamic loader; in Unicode aware Tcl versions
2987 it also helps Tcl find its encodings. */
2988 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00002989
Barry Warsawfa701a81997-01-16 00:15:11 +00002990 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002991 return;
2992
Guido van Rossum43ff8681998-07-14 18:02:13 +00002993#if 0
2994 /* This was not a good idea; through <Destroy> bindings,
2995 Tcl_Finalize() may invoke Python code but at that point the
2996 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002997 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002998#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002999
Jack Jansen34cc5c31995-10-31 16:15:12 +00003000#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003001 /*
3002 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
3003 ** Most of the initializations in that routine (toolbox init calls and
3004 ** such) have already been done for us, so we only need these.
3005 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003006 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003007
3008 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00003009#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00003010 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00003011#endif /* GENERATINGCFM */
3012#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00003013}
Guido van Rossum9722ad81995-09-22 23:49:28 +00003014
Guido van Rossumec22c921996-02-25 04:50:29 +00003015
Barry Warsawfa701a81997-01-16 00:15:11 +00003016
Guido van Rossum9722ad81995-09-22 23:49:28 +00003017#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003018
3019/*
Guido van Rossumec22c921996-02-25 04:50:29 +00003020** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003021*/
3022
Guido van Rossum9722ad81995-09-22 23:49:28 +00003023void
3024panic(char * format, ...)
3025{
Barry Warsawfa701a81997-01-16 00:15:11 +00003026 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003027
Barry Warsawfa701a81997-01-16 00:15:11 +00003028 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003029
Guido van Rossum227cf761998-08-05 13:53:32 +00003030 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00003031 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003032
Barry Warsawfa701a81997-01-16 00:15:11 +00003033 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003034
Barry Warsawfa701a81997-01-16 00:15:11 +00003035 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00003036}
Jack Jansen40b546d1995-11-14 10:34:45 +00003037
Guido van Rossumec22c921996-02-25 04:50:29 +00003038/*
3039** Pass events to SIOUX before passing them to Tk.
3040*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003041
Guido van Rossumec22c921996-02-25 04:50:29 +00003042static int
Fred Drake509d79a2000-07-08 04:04:38 +00003043PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003044{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003045 WindowPtr frontwin;
3046 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00003047 ** Sioux eats too many events, so we don't pass it everything. We
3048 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003049 ** the Sioux window is frontmost. This means that Tk menus don't work
3050 ** in that case, but at least we can scroll the sioux window.
3051 ** Note that the SIOUXIsAppWindow() routine we use here is not really
3052 ** part of the external interface of Sioux...
3053 */
3054 frontwin = FrontWindow();
3055 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
3056 if (SIOUXHandleOneEvent(eventPtr))
3057 return 0; /* Nothing happened to the Tcl event queue */
3058 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003059 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003060}
3061
Guido van Rossumec22c921996-02-25 04:50:29 +00003062#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003063
3064/*
3065** Additional Mac specific code for dealing with shared libraries.
3066*/
3067
3068#include <Resources.h>
3069#include <CodeFragments.h>
3070
3071static int loaded_from_shlib = 0;
3072static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003073
Jack Jansen34cc5c31995-10-31 16:15:12 +00003074/*
3075** If this module is dynamically loaded the following routine should
3076** be the init routine. It takes care of adding the shared library to
3077** the resource-file chain, so that the tk routines can find their
3078** resources.
3079*/
3080OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003081init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003082{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00003083 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00003084 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003085 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003086 library_fss = *data->fragLocator.u.onDisk.fileSpec;
3087 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003088 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003089 library_fss = *data->fragLocator.u.inSegs.fileSpec;
3090 loaded_from_shlib = 1;
3091 }
3092 return noErr;
3093}
3094
3095/*
3096** Insert the library resources into the search path. Put them after
3097** the resources from the application. Again, we ignore errors.
3098*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003099static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003100mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003101{
3102 if ( !loaded_from_shlib )
3103 return;
3104 (void)FSpOpenResFile(&library_fss, fsRdPerm);
3105}
3106
Guido van Rossumec22c921996-02-25 04:50:29 +00003107#endif /* GENERATINGCFM */
3108#endif /* macintosh */