blob: 02e4feb47f30df4ee8b7b060165e13522898228e [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
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000321static int Tkinter_busywaitinterval = 20;
322
Guido van Rossum00d93061998-05-28 23:06:38 +0000323#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000324#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000325
Guido van Rossum00d93061998-05-28 23:06:38 +0000326/* Millisecond sleep() for Unix platforms. */
327
328static void
Fred Drake509d79a2000-07-08 04:04:38 +0000329Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000330{
331 /* XXX Too bad if you don't have select(). */
332 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000333 t.tv_sec = milli/1000;
334 t.tv_usec = (milli%1000) * 1000;
335 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
336}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000337#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000338
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000339/* Wait up to 1s for the mainloop to come up. */
340
341static int
342WaitForMainloop(TkappObject* self)
343{
344 int i;
345 for (i = 0; i < 10; i++) {
346 if (self->dispatching)
347 return 1;
348 Py_BEGIN_ALLOW_THREADS
349 Sleep(100);
350 Py_END_ALLOW_THREADS
351 }
352 if (self->dispatching)
353 return 1;
354 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
355 return 0;
356}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000357#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000358
Guido van Rossum00d93061998-05-28 23:06:38 +0000359
Guido van Rossum18468821994-06-20 07:49:28 +0000360static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000361AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000362{
Guido van Rossum35d43371997-08-02 00:09:09 +0000363 if (PyString_Check(value))
364 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000365#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000366 else if (PyUnicode_Check(value)) {
367 PyObject *v = PyUnicode_AsUTF8String(value);
368 if (v == NULL)
369 return NULL;
370 if (PyList_Append(tmp, v) != 0) {
371 Py_DECREF(v);
372 return NULL;
373 }
374 Py_DECREF(v);
375 return PyString_AsString(v);
376 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000377#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000378 else {
379 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000380 if (v == NULL)
381 return NULL;
382 if (PyList_Append(tmp, v) != 0) {
383 Py_DECREF(v);
384 return NULL;
385 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000386 Py_DECREF(v);
387 return PyString_AsString(v);
388 }
Guido van Rossum18468821994-06-20 07:49:28 +0000389}
390
Barry Warsawfa701a81997-01-16 00:15:11 +0000391
392
Guido van Rossum18468821994-06-20 07:49:28 +0000393#define ARGSZ 64
394
395static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000396Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000397{
Barry Warsawfa701a81997-01-16 00:15:11 +0000398 PyObject *tmp = NULL;
399 char *argvStore[ARGSZ];
400 char **argv = NULL;
401 int fvStore[ARGSZ];
402 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000403 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000404 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000405
Barry Warsawfa701a81997-01-16 00:15:11 +0000406 if (!(tmp = PyList_New(0)))
407 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000408
Barry Warsawfa701a81997-01-16 00:15:11 +0000409 argv = argvStore;
410 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000411
Barry Warsawfa701a81997-01-16 00:15:11 +0000412 if (args == NULL)
413 argc = 0;
414
415 else if (!PyTuple_Check(args)) {
416 argc = 1;
417 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000418 if (!(argv[0] = AsString(args, tmp)))
419 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000420 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000421 else {
422 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000423
Barry Warsawfa701a81997-01-16 00:15:11 +0000424 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000425 argv = (char **)ckalloc(argc * sizeof(char *));
426 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000427 if (argv == NULL || fv == NULL) {
428 PyErr_NoMemory();
429 goto finally;
430 }
431 }
432
433 for (i = 0; i < argc; i++) {
434 PyObject *v = PyTuple_GetItem(args, i);
435 if (PyTuple_Check(v)) {
436 fv[i] = 1;
437 if (!(argv[i] = Merge(v)))
438 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000439 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000440 }
441 else if (v == Py_None) {
442 argc = i;
443 break;
444 }
445 else {
446 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000447 if (!(argv[i] = AsString(v, tmp)))
448 goto finally;
449 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000450 }
451 }
Guido van Rossum18468821994-06-20 07:49:28 +0000452 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000453 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000454 if (res == NULL)
455 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000456
Barry Warsawfa701a81997-01-16 00:15:11 +0000457 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000458 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000459 if (fv[i]) {
460 ckfree(argv[i]);
461 }
462 if (argv != argvStore)
463 ckfree(FREECAST argv);
464 if (fv != fvStore)
465 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000466
Barry Warsawfa701a81997-01-16 00:15:11 +0000467 Py_DECREF(tmp);
468 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000469}
470
Barry Warsawfa701a81997-01-16 00:15:11 +0000471
472
Guido van Rossum18468821994-06-20 07:49:28 +0000473static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000474Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000475{
Barry Warsawfa701a81997-01-16 00:15:11 +0000476 int argc;
477 char **argv;
478 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000479
Barry Warsawfa701a81997-01-16 00:15:11 +0000480 if (list == NULL) {
481 Py_INCREF(Py_None);
482 return Py_None;
483 }
Guido van Rossum18468821994-06-20 07:49:28 +0000484
Guido van Rossum00d93061998-05-28 23:06:38 +0000485 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000486 /* Not a list.
487 * Could be a quoted string containing funnies, e.g. {"}.
488 * Return the string itself.
489 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000490 return PyString_FromString(list);
491 }
Guido van Rossum18468821994-06-20 07:49:28 +0000492
Barry Warsawfa701a81997-01-16 00:15:11 +0000493 if (argc == 0)
494 v = PyString_FromString("");
495 else if (argc == 1)
496 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000497 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000498 int i;
499 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000500
Barry Warsawfa701a81997-01-16 00:15:11 +0000501 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000502 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000503 Py_DECREF(v);
504 v = NULL;
505 break;
506 }
507 PyTuple_SetItem(v, i, w);
508 }
509 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000510 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000511 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000512}
513
Martin v. Löwisffad6332002-11-26 09:28:05 +0000514/* In some cases, Tcl will still return strings that are supposed to be
515 lists. SplitObj walks through a nested tuple, finding string objects that
516 need to be split. */
517
518PyObject *
519SplitObj(PyObject *arg)
520{
521 if (PyTuple_Check(arg)) {
522 int i, size;
523 PyObject *elem, *newelem, *result;
524
525 size = PyTuple_Size(arg);
526 result = NULL;
527 /* Recursively invoke SplitObj for all tuple items.
528 If this does not return a new object, no action is
529 needed. */
530 for(i = 0; i < size; i++) {
531 elem = PyTuple_GetItem(arg, i);
532 newelem = SplitObj(elem);
533 if (!newelem) {
534 Py_XDECREF(result);
535 return NULL;
536 }
537 if (!result) {
538 int k;
539 if (newelem == elem) {
540 Py_DECREF(newelem);
541 continue;
542 }
543 result = PyTuple_New(size);
544 if (!result)
545 return NULL;
546 for(k = 0; k < i; k++) {
547 elem = PyTuple_GetItem(arg, k);
548 Py_INCREF(elem);
549 PyTuple_SetItem(result, k, elem);
550 }
551 }
552 PyTuple_SetItem(result, i, newelem);
553 }
554 if (result)
555 return result;
556 /* Fall through, returning arg. */
557 }
558 else if (PyString_Check(arg)) {
559 int argc;
560 char **argv;
561 char *list = PyString_AsString(arg);
562
563 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
564 Py_INCREF(arg);
565 return arg;
566 }
567 Tcl_Free(FREECAST argv);
568 if (argc > 1)
569 return Split(PyString_AsString(arg));
570 /* Fall through, returning arg. */
571 }
572 Py_INCREF(arg);
573 return arg;
574}
Barry Warsawfa701a81997-01-16 00:15:11 +0000575
576
Guido van Rossum18468821994-06-20 07:49:28 +0000577/**** Tkapp Object ****/
578
579#ifndef WITH_APPINIT
580int
Fred Drake509d79a2000-07-08 04:04:38 +0000581Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000582{
Barry Warsawfa701a81997-01-16 00:15:11 +0000583 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000584
Barry Warsawfa701a81997-01-16 00:15:11 +0000585 main = Tk_MainWindow(interp);
586 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000587 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000588 return TCL_ERROR;
589 }
590 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000591 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000592 return TCL_ERROR;
593 }
594 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000595}
596#endif /* !WITH_APPINIT */
597
Guido van Rossum18468821994-06-20 07:49:28 +0000598
Barry Warsawfa701a81997-01-16 00:15:11 +0000599
600
601/* Initialize the Tk application; see the `main' function in
602 * `tkMain.c'.
603 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000604
Thomas Wouters58d05102000-07-24 14:43:35 +0000605static void EnableEventHook(void); /* Forward */
606static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000607
Barry Warsawfa701a81997-01-16 00:15:11 +0000608static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000609Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000610 int interactive, int wantobjects)
Barry Warsawfa701a81997-01-16 00:15:11 +0000611{
612 TkappObject *v;
613 char *argv0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000614
Guido van Rossumb18618d2000-05-03 23:44:39 +0000615 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000616 if (v == NULL)
617 return NULL;
618
619 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000620 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000621 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
622 TCL_GLOBAL_ONLY) != NULL;
623 v->thread_id = Tcl_GetCurrentThread();
624 v->dispatching = 0;
625
626#ifndef TCL_THREADS
627 if (v->threaded) {
628 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
629 Py_DECREF(v);
630 return 0;
631 }
632#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000633#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000634 if (v->threaded && tcl_lock) {
635 /* If Tcl is threaded, we don't need the lock. */
636 PyThread_free_lock(tcl_lock);
637 tcl_lock = NULL;
638 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000639#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000640
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000641 v->BooleanType = Tcl_GetObjType("boolean");
642 v->ByteArrayType = Tcl_GetObjType("bytearray");
643 v->DoubleType = Tcl_GetObjType("double");
644 v->IntType = Tcl_GetObjType("int");
645 v->ListType = Tcl_GetObjType("list");
646 v->ProcBodyType = Tcl_GetObjType("procbody");
647 v->StringType = Tcl_GetObjType("string");
648
Guido van Rossuma80649b2000-03-28 20:07:05 +0000649#if defined(macintosh)
650 /* This seems to be needed */
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000651 ClearMenuBar();
652 TkMacInitMenus(v->interp);
653#endif
Jack Jansencb852442001-12-09 23:15:56 +0000654
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000655 /* Delete the 'exit' command, which can screw things up */
656 Tcl_DeleteCommand(v->interp, "exit");
657
Barry Warsawfa701a81997-01-16 00:15:11 +0000658 if (screenName != NULL)
659 Tcl_SetVar2(v->interp, "env", "DISPLAY",
660 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000661
Barry Warsawfa701a81997-01-16 00:15:11 +0000662 if (interactive)
663 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
664 else
665 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000666
Barry Warsawfa701a81997-01-16 00:15:11 +0000667 /* This is used to get the application class for Tk 4.1 and up */
668 argv0 = (char*)ckalloc(strlen(className) + 1);
669 if (!argv0) {
670 PyErr_NoMemory();
671 Py_DECREF(v);
672 return NULL;
673 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000674
Barry Warsawfa701a81997-01-16 00:15:11 +0000675 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000676 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000677 argv0[0] = tolower(argv0[0]);
678 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
679 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000680
Barry Warsawfa701a81997-01-16 00:15:11 +0000681 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000682 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000683
Guido van Rossum7bf15641998-05-22 18:28:17 +0000684 EnableEventHook();
685
Barry Warsawfa701a81997-01-16 00:15:11 +0000686 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000687}
688
Barry Warsawfa701a81997-01-16 00:15:11 +0000689
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000690static void
691Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
692 Tcl_Condition *cond, Tcl_Mutex *mutex)
693{
694 Py_BEGIN_ALLOW_THREADS;
695 Tcl_MutexLock(mutex);
696 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
697 Tcl_ThreadAlert(self->thread_id);
698 Tcl_ConditionWait(cond, mutex, NULL);
699 Tcl_MutexUnlock(mutex);
700 Py_END_ALLOW_THREADS
701}
702
Barry Warsawfa701a81997-01-16 00:15:11 +0000703
Guido van Rossum18468821994-06-20 07:49:28 +0000704/** Tcl Eval **/
705
Martin v. Löwisffad6332002-11-26 09:28:05 +0000706typedef struct {
707 PyObject_HEAD
708 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000709 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000710} PyTclObject;
711
712staticforward PyTypeObject PyTclObject_Type;
713#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
714
715static PyObject *
716newPyTclObject(Tcl_Obj *arg)
717{
718 PyTclObject *self;
719 self = PyObject_New(PyTclObject, &PyTclObject_Type);
720 if (self == NULL)
721 return NULL;
722 Tcl_IncrRefCount(arg);
723 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000724 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000725 return (PyObject*)self;
726}
727
728static void
729PyTclObject_dealloc(PyTclObject *self)
730{
731 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000732 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000733 PyObject_Del(self);
734}
735
736static PyObject *
737PyTclObject_str(PyTclObject *self)
738{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000739 if (self->string && PyString_Check(self->string)) {
740 Py_INCREF(self->string);
741 return self->string;
742 }
743 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000744 return PyString_FromString(Tcl_GetString(self->value));
745}
746
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000747static char*
748PyTclObject_TclString(PyObject *self)
749{
750 return Tcl_GetString(((PyTclObject*)self)->value);
751}
752
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000753/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000754PyDoc_STRVAR(PyTclObject_string__doc__,
755"the string representation of this object, either as string or Unicode");
756
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000757static PyObject *
758PyTclObject_string(PyTclObject *self, void *ignored)
759{
760 char *s;
761 int i, len;
762 if (!self->string) {
763 s = Tcl_GetStringFromObj(self->value, &len);
764 for (i = 0; i < len; i++)
765 if (s[i] & 0x80)
766 break;
767#ifdef Py_USING_UNICODE
768 if (i == len)
769 /* It is an ASCII string. */
770 self->string = PyString_FromStringAndSize(s, len);
771 else {
772 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
773 if (!self->string) {
774 PyErr_Clear();
775 self->string = PyString_FromStringAndSize(s, len);
776 }
777 }
778#else
779 self->string = PyString_FromStringAndSize(s, len);
780#endif
781 if (!self->string)
782 return NULL;
783 }
784 Py_INCREF(self->string);
785 return self->string;
786}
787
788#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000789PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
790
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000791static PyObject *
792PyTclObject_unicode(PyTclObject *self, void *ignored)
793{
794 char *s;
795 int len;
796 if (self->string && PyUnicode_Check(self->string)) {
797 Py_INCREF(self->string);
798 return self->string;
799 }
800 /* XXX Could chache result if it is non-ASCII. */
801 s = Tcl_GetStringFromObj(self->value, &len);
802 return PyUnicode_DecodeUTF8(s, len, "strict");
803}
804#endif
805
Martin v. Löwisffad6332002-11-26 09:28:05 +0000806static PyObject *
807PyTclObject_repr(PyTclObject *self)
808{
809 char buf[50];
810 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
811 self->value->typePtr->name, (int)self->value);
812 return PyString_FromString(buf);
813}
814
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000815static int
816PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
817{
818 int res;
819 res = strcmp(Tcl_GetString(self->value),
820 Tcl_GetString(other->value));
821 if (res < 0) return -1;
822 if (res > 0) return 1;
823 return 0;
824}
825
Martin v. Löwis39195712003-01-04 00:33:13 +0000826PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
827
Martin v. Löwisffad6332002-11-26 09:28:05 +0000828static PyObject*
829get_typename(PyTclObject* obj, void* ignored)
830{
831 return PyString_FromString(obj->value->typePtr->name);
832}
833
Martin v. Löwis39195712003-01-04 00:33:13 +0000834
Martin v. Löwisffad6332002-11-26 09:28:05 +0000835static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000836 {"typename", (getter)get_typename, NULL, get_typename__doc__},
837 {"string", (getter)PyTclObject_string, NULL,
838 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000839 {0},
840};
841
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000842static PyMethodDef PyTclObject_methods[] = {
843 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000844 PyTclObject_unicode__doc__},
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000845 {0}
846};
847
Martin v. Löwisffad6332002-11-26 09:28:05 +0000848statichere PyTypeObject PyTclObject_Type = {
849 PyObject_HEAD_INIT(NULL)
850 0, /*ob_size*/
851 "_tkinter.Tcl_Obj", /*tp_name*/
852 sizeof(PyTclObject), /*tp_basicsize*/
853 0, /*tp_itemsize*/
854 /* methods */
855 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
856 0, /*tp_print*/
857 0, /*tp_getattr*/
858 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000859 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000860 (reprfunc)PyTclObject_repr, /*tp_repr*/
861 0, /*tp_as_number*/
862 0, /*tp_as_sequence*/
863 0, /*tp_as_mapping*/
864 0, /*tp_hash*/
865 0, /*tp_call*/
866 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000867 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000868 0, /*tp_setattro*/
869 0, /*tp_as_buffer*/
870 Py_TPFLAGS_DEFAULT, /*tp_flags*/
871 0, /*tp_doc*/
872 0, /*tp_traverse*/
873 0, /*tp_clear*/
874 0, /*tp_richcompare*/
875 0, /*tp_weaklistoffset*/
876 0, /*tp_iter*/
877 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000878 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000879 0, /*tp_members*/
880 PyTclObject_getsetlist, /*tp_getset*/
881 0, /*tp_base*/
882 0, /*tp_dict*/
883 0, /*tp_descr_get*/
884 0, /*tp_descr_set*/
885 0, /*tp_dictoffset*/
886 0, /*tp_init*/
887 0, /*tp_alloc*/
888 0, /*tp_new*/
889 0, /*tp_free*/
890 0, /*tp_is_gc*/
891};
892
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000893static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000894AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000895{
896 Tcl_Obj *result;
897
898 if (PyString_Check(value))
899 return Tcl_NewStringObj(PyString_AS_STRING(value),
900 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000901 else if (PyBool_Check(value))
902 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000903 else if (PyInt_Check(value))
904 return Tcl_NewLongObj(PyInt_AS_LONG(value));
905 else if (PyFloat_Check(value))
906 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
907 else if (PyTuple_Check(value)) {
908 Tcl_Obj **argv = (Tcl_Obj**)
909 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
910 int i;
911 if(!argv)
912 return 0;
913 for(i=0;i<PyTuple_Size(value);i++)
914 argv[i] = AsObj(PyTuple_GetItem(value,i));
915 result = Tcl_NewListObj(PyTuple_Size(value), argv);
916 ckfree(FREECAST argv);
917 return result;
918 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000919#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000920 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000921 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
922 int size = PyUnicode_GET_SIZE(value);
923 /* This #ifdef assumes that Tcl uses UCS-2.
924 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000925#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000926 Tcl_UniChar *outbuf;
927 int i;
928 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
929 if (!outbuf) {
930 PyErr_NoMemory();
931 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000932 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000933 for (i = 0; i < size; i++) {
934 if (inbuf[i] >= 0x10000) {
935 /* Tcl doesn't do UTF-16, yet. */
936 PyErr_SetString(PyExc_ValueError,
937 "unsupported character");
938 ckfree(FREECAST outbuf);
939 return NULL;
940 }
941 outbuf[i] = inbuf[i];
942 }
943 result = Tcl_NewUnicodeObj(outbuf, size);
944 ckfree(FREECAST outbuf);
945 return result;
946#else
947 return Tcl_NewUnicodeObj(inbuf, size);
948#endif
949
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000950 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000951#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000952 else if(PyTclObject_Check(value)) {
953 Tcl_Obj *v = ((PyTclObject*)value)->value;
954 Tcl_IncrRefCount(v);
955 return v;
956 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000957 else {
958 PyObject *v = PyObject_Str(value);
959 if (!v)
960 return 0;
961 result = AsObj(v);
962 Py_DECREF(v);
963 return result;
964 }
965}
966
Martin v. Löwisffad6332002-11-26 09:28:05 +0000967static PyObject*
968FromObj(PyObject* tkapp, Tcl_Obj *value)
969{
970 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000971 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000972
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000973 if (value->typePtr == NULL) {
974 /* If the result contains any bytes with the top bit set,
975 it's UTF-8 and we should decode it to Unicode */
976#ifdef Py_USING_UNICODE
977 int i;
978 char *s = value->bytes;
979 int len = value->length;
980 for (i = 0; i < len; i++) {
981 if (value->bytes[i] & 0x80)
982 break;
983 }
984
985 if (i == value->length)
986 result = PyString_FromStringAndSize(s, len);
987 else {
988 /* Convert UTF-8 to Unicode string */
989 result = PyUnicode_DecodeUTF8(s, len, "strict");
990 if (result == NULL) {
991 PyErr_Clear();
992 result = PyString_FromStringAndSize(s, len);
993 }
994 }
995#else
996 res = PyString_FromStringAndSize(value->bytes, value->length);
997#endif
998 return result;
999 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001000
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001001 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001002 result = value->internalRep.longValue ? Py_True : Py_False;
1003 Py_INCREF(result);
1004 return result;
1005 }
1006
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001007 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001008 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +00001009 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001010 return PyString_FromStringAndSize(data, size);
1011 }
1012
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001013 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001014 return PyFloat_FromDouble(value->internalRep.doubleValue);
1015 }
1016
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001017 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001018 return PyInt_FromLong(value->internalRep.longValue);
1019 }
1020
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001021 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001022 int size;
1023 int i, status;
1024 PyObject *elem;
1025 Tcl_Obj *tcl_elem;
1026
1027 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1028 if (status == TCL_ERROR)
1029 return Tkinter_Error(tkapp);
1030 result = PyTuple_New(size);
1031 if (!result)
1032 return NULL;
1033 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001034 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001035 value, i, &tcl_elem);
1036 if (status == TCL_ERROR) {
1037 Py_DECREF(result);
1038 return Tkinter_Error(tkapp);
1039 }
1040 elem = FromObj(tkapp, tcl_elem);
1041 if (!elem) {
1042 Py_DECREF(result);
1043 return NULL;
1044 }
1045 PyTuple_SetItem(result, i, elem);
1046 }
1047 return result;
1048 }
1049
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001050 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001051 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001052 }
1053
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001054 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001055#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001056#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001057 PyObject *result;
1058 int size;
1059 Tcl_UniChar *input;
1060 Py_UNICODE *output;
1061
1062 size = Tcl_GetCharLength(value);
1063 result = PyUnicode_FromUnicode(NULL, size);
1064 if (!result)
1065 return NULL;
1066 input = Tcl_GetUnicode(value);
1067 output = PyUnicode_AS_UNICODE(result);
1068 while (size--)
1069 *output++ = *input++;
1070 return result;
1071#else
1072 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1073 Tcl_GetCharLength(value));
1074#endif
1075#else
1076 int size;
1077 char *c;
1078 c = Tcl_GetStringFromObj(value, &size);
1079 return PyString_FromStringAndSize(c, size);
1080#endif
1081 }
1082
1083 return newPyTclObject(value);
1084}
1085
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001086/* This mutex synchronizes inter-thread command calls. */
1087
1088TCL_DECLARE_MUTEX(call_mutex)
1089
1090typedef struct Tkapp_CallEvent {
1091 Tcl_Event ev; /* Must be first */
1092 TkappObject *self;
1093 PyObject *args;
1094 int flags;
1095 PyObject **res;
1096 PyObject **exc_type, **exc_value, **exc_tb;
1097 Tcl_Condition done;
1098} Tkapp_CallEvent;
1099
1100void
1101Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001102{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001103 int i;
1104 for (i = 0; i < objc; i++)
1105 Tcl_DecrRefCount(objv[i]);
1106 if (objv != objStore)
1107 ckfree(FREECAST objv);
1108}
Guido van Rossum18468821994-06-20 07:49:28 +00001109
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001110/* Convert Python objects to Tcl objects. This must happen in the
1111 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001112
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001113static Tcl_Obj**
1114Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1115{
1116 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001117 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001118 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001119 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001120
Guido van Rossum212643f1998-04-29 16:22:14 +00001121 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001122 objv[0] = AsObj(args);
1123 if (objv[0] == 0)
1124 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001125 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001126 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001127 }
1128 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001129 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001130
Guido van Rossum632de272000-03-29 00:19:50 +00001131 if (objc > ARGSZ) {
1132 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1133 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001134 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001135 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001136 goto finally;
1137 }
1138 }
1139
Guido van Rossum632de272000-03-29 00:19:50 +00001140 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001141 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001142 if (v == Py_None) {
1143 objc = i;
1144 break;
1145 }
Guido van Rossum632de272000-03-29 00:19:50 +00001146 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001147 if (!objv[i]) {
1148 /* Reset objc, so it attempts to clear
1149 objects only up to i. */
1150 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001151 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001152 }
Guido van Rossum632de272000-03-29 00:19:50 +00001153 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001154 }
1155 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001156 *pobjc = objc;
1157 return objv;
1158finally:
1159 Tkapp_CallDeallocArgs(objv, objStore, objc);
1160 return NULL;
1161}
Guido van Rossum212643f1998-04-29 16:22:14 +00001162
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001163/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001164
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001165static PyObject*
1166Tkapp_CallResult(TkappObject *self)
1167{
1168 PyObject *res = NULL;
1169 if(self->wantobjects) {
1170 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001171 /* Not sure whether the IncrRef is necessary, but something
1172 may overwrite the interpreter result while we are
1173 converting it. */
1174 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001175 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001176 Tcl_DecrRefCount(value);
1177 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001178 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001179 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001180
Guido van Rossum990f5c62000-05-04 15:07:16 +00001181 /* If the result contains any bytes with the top bit set,
1182 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001183#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001184 while (*p != '\0') {
1185 if (*p & 0x80)
1186 break;
1187 p++;
1188 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001189
Guido van Rossum990f5c62000-05-04 15:07:16 +00001190 if (*p == '\0')
1191 res = PyString_FromStringAndSize(s, (int)(p-s));
1192 else {
1193 /* Convert UTF-8 to Unicode string */
1194 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001195 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1196 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001197 PyErr_Clear();
1198 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001199 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001200 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001201#else
1202 p = strchr(p, '\0');
1203 res = PyString_FromStringAndSize(s, (int)(p-s));
1204#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001205 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001206 return res;
1207}
Guido van Rossum632de272000-03-29 00:19:50 +00001208
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001209/* Tkapp_CallProc is the event procedure that is executed in the context of
1210 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1211 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001212
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001213static int
1214Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1215{
1216 Tcl_Obj *objStore[ARGSZ];
1217 Tcl_Obj **objv;
1218 int objc;
1219 int i;
1220 ENTER_PYTHON
1221 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1222 if (!objv) {
1223 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1224 *(e->res) = NULL;
1225 }
1226 LEAVE_PYTHON
1227 if (!objv)
1228 goto done;
1229 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1230 ENTER_PYTHON
1231 if (i == TCL_ERROR) {
1232 *(e->res) = NULL;
1233 *(e->exc_type) = NULL;
1234 *(e->exc_tb) = NULL;
1235 *(e->exc_value) = PyObject_CallFunction(
1236 Tkinter_TclError, "s",
1237 Tcl_GetStringResult(e->self->interp));
1238 }
1239 else {
1240 *(e->res) = Tkapp_CallResult(e->self);
1241 }
1242 LEAVE_PYTHON
1243 done:
1244 /* Wake up calling thread. */
1245 Tcl_MutexLock(&call_mutex);
1246 Tcl_ConditionNotify(&e->done);
1247 Tcl_MutexUnlock(&call_mutex);
1248 return 1;
1249}
1250
1251/* This is the main entry point for calling a Tcl command.
1252 It supports three cases, with regard to threading:
1253 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1254 the context of the calling thread.
1255 2. Tcl is threaded, caller of the command is in the interpreter thread:
1256 Execute the command in the calling thread. Since the Tcl lock will
1257 not be used, we can merge that with case 1.
1258 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1259 the interpreter thread. Allocation of Tcl objects needs to occur in the
1260 interpreter thread, so we ship the PyObject* args to the target thread,
1261 and perform processing there. */
1262
1263static PyObject *
1264Tkapp_Call(PyObject *_self, PyObject *args)
1265{
1266 Tcl_Obj *objStore[ARGSZ];
1267 Tcl_Obj **objv = NULL;
1268 int objc, i;
1269 PyObject *res = NULL;
1270 TkappObject *self = (TkappObject*)_self;
1271 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1272 int flags = TCL_EVAL_DIRECT;
1273
Martin v. Löwisa9656492003-03-30 08:44:58 +00001274#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001275 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1276 /* We cannot call the command directly. Instead, we must
1277 marshal the parameters to the interpreter thread. */
1278 Tkapp_CallEvent *ev;
1279 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001280 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001281 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001282 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1283 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1284 ev->self = self;
1285 ev->args = args;
1286 ev->res = &res;
1287 ev->exc_type = &exc_type;
1288 ev->exc_value = &exc_value;
1289 ev->exc_tb = &exc_tb;
1290 ev->done = (Tcl_Condition)0;
1291
1292 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1293
1294 if (res == NULL) {
1295 if (exc_type)
1296 PyErr_Restore(exc_type, exc_value, exc_tb);
1297 else
1298 PyErr_SetObject(Tkinter_TclError, exc_value);
1299 }
1300 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001301 else
1302#endif
1303 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001304
1305 objv = Tkapp_CallArgs(args, objStore, &objc);
1306 if (!objv)
1307 return NULL;
1308
1309 ENTER_TCL
1310
1311 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1312
1313 ENTER_OVERLAP
1314
1315 if (i == TCL_ERROR)
1316 Tkinter_Error(_self);
1317 else
1318 res = Tkapp_CallResult(self);
1319
1320 LEAVE_OVERLAP_TCL
1321
1322 Tkapp_CallDeallocArgs(objv, objStore, objc);
1323 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001324 return res;
1325}
1326
1327
1328static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001329Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001330{
Guido van Rossum212643f1998-04-29 16:22:14 +00001331 /* Could do the same here as for Tkapp_Call(), but this is not used
1332 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1333 way for the user to do what all its Global* variants do (save and
1334 reset the scope pointer, call the local version, restore the saved
1335 scope pointer). */
1336
Guido van Rossum62320c91998-06-15 04:36:09 +00001337 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001338 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001339
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001340 CHECK_TCL_APPARTMENT;
1341
Guido van Rossum62320c91998-06-15 04:36:09 +00001342 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001343 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001344 int err;
1345 ENTER_TCL
1346 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001347 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001348 if (err == TCL_ERROR)
1349 res = Tkinter_Error(self);
1350 else
1351 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001352 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001353 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001354 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001355
1356 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001357}
1358
1359static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001360Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001361{
Barry Warsawfa701a81997-01-16 00:15:11 +00001362 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001363 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001364 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001365
Guido van Rossum43713e52000-02-29 13:59:29 +00001366 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001367 return NULL;
1368
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001369 CHECK_TCL_APPARTMENT;
1370
Guido van Rossum00d93061998-05-28 23:06:38 +00001371 ENTER_TCL
1372 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001373 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001374 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001375 res = Tkinter_Error(self);
1376 else
1377 res = PyString_FromString(Tkapp_Result(self));
1378 LEAVE_OVERLAP_TCL
1379 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001380}
1381
1382static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001383Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001384{
Barry Warsawfa701a81997-01-16 00:15:11 +00001385 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001386 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001387 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001388
Guido van Rossum43713e52000-02-29 13:59:29 +00001389 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001390 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001391
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001392 CHECK_TCL_APPARTMENT;
1393
Guido van Rossum00d93061998-05-28 23:06:38 +00001394 ENTER_TCL
1395 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001396 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001397 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001398 res = Tkinter_Error(self);
1399 else
1400 res = PyString_FromString(Tkapp_Result(self));
1401 LEAVE_OVERLAP_TCL
1402 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001403}
1404
1405static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001406Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001407{
Barry Warsawfa701a81997-01-16 00:15:11 +00001408 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001409 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001410 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001411
Guido van Rossum43713e52000-02-29 13:59:29 +00001412 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001413 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001414
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001415 CHECK_TCL_APPARTMENT;
1416
Guido van Rossum00d93061998-05-28 23:06:38 +00001417 ENTER_TCL
1418 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001419 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001420 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001421 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001422
Guido van Rossum62320c91998-06-15 04:36:09 +00001423 else
1424 res = PyString_FromString(Tkapp_Result(self));
1425 LEAVE_OVERLAP_TCL
1426 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001427}
1428
1429static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001430Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001431{
Barry Warsawfa701a81997-01-16 00:15:11 +00001432 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001433 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001434 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001435
Guido van Rossum35d43371997-08-02 00:09:09 +00001436 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001437 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001438
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001439 CHECK_TCL_APPARTMENT;
1440
Guido van Rossum00d93061998-05-28 23:06:38 +00001441 ENTER_TCL
1442 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001443 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001444 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001445 res = Tkinter_Error(self);
1446 else
1447 res = PyString_FromString(Tkapp_Result(self));
1448 LEAVE_OVERLAP_TCL
1449 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001450}
1451
1452static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001453Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001454{
Barry Warsawfa701a81997-01-16 00:15:11 +00001455 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001456
Guido van Rossum43713e52000-02-29 13:59:29 +00001457 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001458 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001459 CHECK_TCL_APPARTMENT;
1460
Guido van Rossum00d93061998-05-28 23:06:38 +00001461 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001462 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001463 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001464
Barry Warsawfa701a81997-01-16 00:15:11 +00001465 Py_INCREF(Py_None);
1466 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001467}
1468
Barry Warsawfa701a81997-01-16 00:15:11 +00001469
1470
Guido van Rossum18468821994-06-20 07:49:28 +00001471/** Tcl Variable **/
1472
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001473TCL_DECLARE_MUTEX(var_mutex)
1474
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001475typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001476typedef struct VarEvent {
1477 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001478 PyObject *self;
1479 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001480 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001481 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001482 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001483 PyObject **exc_type;
1484 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001485 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486} VarEvent;
1487
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001488static int
1489varname_converter(PyObject *in, void *_out)
1490{
1491 char **out = (char**)_out;
1492 if (PyString_Check(in)) {
1493 *out = PyString_AsString(in);
1494 return 1;
1495 }
1496 if (PyTclObject_Check(in)) {
1497 *out = PyTclObject_TclString(in);
1498 return 1;
1499 }
1500 /* XXX: Should give diagnostics. */
1501 return 0;
1502}
1503
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001504void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001505var_perform(VarEvent *ev)
1506{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001507 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1508 if (!*(ev->res)) {
1509 PyObject *exc, *val, *tb;
1510 PyErr_Fetch(&exc, &val, &tb);
1511 PyErr_NormalizeException(&exc, &val, &tb);
1512 *(ev->exc_type) = exc;
1513 *(ev->exc_val) = val;
1514 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001515 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001516
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001517}
1518
1519static int
1520var_proc(VarEvent* ev, int flags)
1521{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001522 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001523 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001524 Tcl_MutexLock(&var_mutex);
1525 Tcl_ConditionNotify(&ev->cond);
1526 Tcl_MutexUnlock(&var_mutex);
1527 LEAVE_PYTHON
1528 return 1;
1529}
1530
1531static PyObject*
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001532var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001533{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001534 TkappObject *self = (TkappObject*)_self;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001535#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001537 TkappObject *self = (TkappObject*)_self;
1538 VarEvent *ev;
1539 PyObject *res, *exc_type, *exc_val;
1540
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001541 /* The current thread is not the interpreter thread. Marshal
1542 the call to the interpreter thread, then wait for
1543 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001544 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001545 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001546
1547 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1548
1549 ev->self = _self;
1550 ev->args = args;
1551 ev->flags = flags;
1552 ev->func = func;
1553 ev->res = &res;
1554 ev->exc_type = &exc_type;
1555 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001556 ev->cond = NULL;
1557 ev->ev.proc = (Tcl_EventProc*)var_proc;
1558 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001559 if (!res) {
1560 PyErr_SetObject(exc_type, exc_val);
1561 Py_DECREF(exc_type);
1562 Py_DECREF(exc_val);
1563 return NULL;
1564 }
1565 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001566 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001567#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001568 /* Tcl is not threaded, or this is the interpreter thread. */
1569 return func(_self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001570}
1571
Guido van Rossum18468821994-06-20 07:49:28 +00001572static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001573SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001574{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001575 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001576 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001577 PyObject *res = NULL;
1578 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001579
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001580 if (PyArg_ParseTuple(args, "O&O:setvar",
1581 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001582 /* XXX Acquire tcl lock??? */
1583 newval = AsObj(newValue);
1584 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001585 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001586 ENTER_TCL
1587 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1588 newval, flags);
1589 ENTER_OVERLAP
1590 if (!ok)
1591 Tkinter_Error(self);
1592 else {
1593 res = Py_None;
1594 Py_INCREF(res);
1595 }
1596 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001597 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001598 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001599 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001600 if (PyArg_ParseTuple(args, "ssO:setvar",
1601 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001602 /* XXX must hold tcl lock already??? */
1603 newval = AsObj(newValue);
1604 ENTER_TCL
1605 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1606 ENTER_OVERLAP
1607 if (!ok)
1608 Tkinter_Error(self);
1609 else {
1610 res = Py_None;
1611 Py_INCREF(res);
1612 }
1613 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001614 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001615 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001616 return NULL;
1617 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001618 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001619 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001620}
1621
1622static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001623Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001624{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001625 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001626}
1627
1628static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001629Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001630{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001631 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001632}
1633
Barry Warsawfa701a81997-01-16 00:15:11 +00001634
1635
Guido van Rossum18468821994-06-20 07:49:28 +00001636static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001637GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001638{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001639 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001640 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001641 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001642
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001643 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1644 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001645 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001646
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001647 ENTER_TCL
1648 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1649 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001650 if (tres == NULL) {
1651 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1652 } else {
1653 if (((TkappObject*)self)->wantobjects) {
1654 res = FromObj(self, tres);
1655 }
1656 else {
1657 res = PyString_FromString(Tcl_GetString(tres));
1658 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001659 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001660 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001661 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001662}
1663
1664static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001665Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001666{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001667 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001668}
1669
1670static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001671Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001672{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001673 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001674}
1675
Barry Warsawfa701a81997-01-16 00:15:11 +00001676
1677
Guido van Rossum18468821994-06-20 07:49:28 +00001678static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001679UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001680{
Guido van Rossum35d43371997-08-02 00:09:09 +00001681 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001682 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001683 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001684
Guido van Rossum43713e52000-02-29 13:59:29 +00001685 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001686 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001687
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001688 ENTER_TCL
1689 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1690 ENTER_OVERLAP
1691 if (code == TCL_ERROR)
1692 res = Tkinter_Error(self);
1693 else {
1694 Py_INCREF(Py_None);
1695 res = Py_None;
1696 }
1697 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001698 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001699}
1700
1701static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001702Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001703{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001704 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001705}
1706
1707static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001708Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001709{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001710 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001711}
1712
Barry Warsawfa701a81997-01-16 00:15:11 +00001713
1714
Guido van Rossum18468821994-06-20 07:49:28 +00001715/** Tcl to Python **/
1716
1717static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001718Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001719{
Barry Warsawfa701a81997-01-16 00:15:11 +00001720 char *s;
1721 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001722
Martin v. Löwisffad6332002-11-26 09:28:05 +00001723 if (PyTuple_Size(args) == 1) {
1724 PyObject* o = PyTuple_GetItem(args, 0);
1725 if (PyInt_Check(o)) {
1726 Py_INCREF(o);
1727 return o;
1728 }
1729 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001730 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001731 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001732 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001733 return Tkinter_Error(self);
1734 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001735}
1736
1737static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001738Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001739{
Barry Warsawfa701a81997-01-16 00:15:11 +00001740 char *s;
1741 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001742
Martin v. Löwisffad6332002-11-26 09:28:05 +00001743 if (PyTuple_Size(args) == 1) {
1744 PyObject *o = PyTuple_GetItem(args, 0);
1745 if (PyFloat_Check(o)) {
1746 Py_INCREF(o);
1747 return o;
1748 }
1749 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001750 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001751 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001752 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001753 return Tkinter_Error(self);
1754 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001755}
1756
1757static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001758Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001759{
Barry Warsawfa701a81997-01-16 00:15:11 +00001760 char *s;
1761 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001762
Martin v. Löwisffad6332002-11-26 09:28:05 +00001763 if (PyTuple_Size(args) == 1) {
1764 PyObject *o = PyTuple_GetItem(args, 0);
1765 if (PyInt_Check(o)) {
1766 Py_INCREF(o);
1767 return o;
1768 }
1769 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001770 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001771 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001772 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1773 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001774 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001775}
1776
1777static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001778Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001779{
Barry Warsawfa701a81997-01-16 00:15:11 +00001780 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001781 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001782 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001783
Guido van Rossum43713e52000-02-29 13:59:29 +00001784 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001785 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001786
1787 CHECK_TCL_APPARTMENT;
1788
Guido van Rossum00d93061998-05-28 23:06:38 +00001789 ENTER_TCL
1790 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001791 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001792 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001793 res = Tkinter_Error(self);
1794 else
1795 res = Py_BuildValue("s", Tkapp_Result(self));
1796 LEAVE_OVERLAP_TCL
1797 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001798}
1799
1800static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001801Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001802{
Barry Warsawfa701a81997-01-16 00:15:11 +00001803 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001804 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001805 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001806 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001807
Guido van Rossum43713e52000-02-29 13:59:29 +00001808 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001809 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001810
1811 CHECK_TCL_APPARTMENT;
1812
Guido van Rossum00d93061998-05-28 23:06:38 +00001813 ENTER_TCL
1814 retval = Tcl_ExprLong(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("l", v);
1820 LEAVE_OVERLAP_TCL
1821 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001822}
1823
1824static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001825Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001826{
Barry Warsawfa701a81997-01-16 00:15:11 +00001827 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001828 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001829 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001830 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001831
Guido van Rossum43713e52000-02-29 13:59:29 +00001832 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001833 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001834 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001835 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001836 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001837 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001838 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001839 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001840 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001841 res = Tkinter_Error(self);
1842 else
1843 res = Py_BuildValue("d", v);
1844 LEAVE_OVERLAP_TCL
1845 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001846}
1847
1848static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001849Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001850{
Barry Warsawfa701a81997-01-16 00:15:11 +00001851 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001852 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001853 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001854 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001855
Guido van Rossum43713e52000-02-29 13:59:29 +00001856 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001857 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001858 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001859 ENTER_TCL
1860 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001861 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001862 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001863 res = Tkinter_Error(self);
1864 else
1865 res = Py_BuildValue("i", v);
1866 LEAVE_OVERLAP_TCL
1867 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001868}
1869
Barry Warsawfa701a81997-01-16 00:15:11 +00001870
1871
Guido van Rossum18468821994-06-20 07:49:28 +00001872static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001873Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001874{
Barry Warsawfa701a81997-01-16 00:15:11 +00001875 char *list;
1876 int argc;
1877 char **argv;
1878 PyObject *v;
1879 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001880
Martin v. Löwisffad6332002-11-26 09:28:05 +00001881 if (PyTuple_Size(args) == 1) {
1882 v = PyTuple_GetItem(args, 0);
1883 if (PyTuple_Check(v)) {
1884 Py_INCREF(v);
1885 return v;
1886 }
1887 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001888 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001889 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001890
Neal Norwitzd1c55102003-05-29 00:17:03 +00001891 if (Tcl_SplitList(Tkapp_Interp(self), list,
1892 &argc, &argv) == TCL_ERROR) {
1893 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001894 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001895 }
Guido van Rossum18468821994-06-20 07:49:28 +00001896
Barry Warsawfa701a81997-01-16 00:15:11 +00001897 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001898 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001899
Barry Warsawfa701a81997-01-16 00:15:11 +00001900 for (i = 0; i < argc; i++) {
1901 PyObject *s = PyString_FromString(argv[i]);
1902 if (!s || PyTuple_SetItem(v, i, s)) {
1903 Py_DECREF(v);
1904 v = NULL;
1905 goto finally;
1906 }
1907 }
Guido van Rossum18468821994-06-20 07:49:28 +00001908
Barry Warsawfa701a81997-01-16 00:15:11 +00001909 finally:
1910 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001911 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001912 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001913}
1914
1915static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001916Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001917{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001918 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001919 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001920
Martin v. Löwisffad6332002-11-26 09:28:05 +00001921 if (PyTuple_Size(args) == 1) {
1922 PyObject* o = PyTuple_GetItem(args, 0);
1923 if (PyTuple_Check(o)) {
1924 o = SplitObj(o);
1925 return o;
1926 }
1927 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001928 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001929 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001930 v = Split(list);
1931 PyMem_Free(list);
1932 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001933}
1934
1935static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001936Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001937{
Barry Warsawfa701a81997-01-16 00:15:11 +00001938 char *s = Merge(args);
1939 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001940
Barry Warsawfa701a81997-01-16 00:15:11 +00001941 if (s) {
1942 res = PyString_FromString(s);
1943 ckfree(s);
1944 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001945
1946 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001947}
1948
Barry Warsawfa701a81997-01-16 00:15:11 +00001949
1950
Guido van Rossum18468821994-06-20 07:49:28 +00001951/** Tcl Command **/
1952
Guido van Rossum00d93061998-05-28 23:06:38 +00001953/* Client data struct */
1954typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001955 PyObject *self;
1956 PyObject *func;
1957} PythonCmd_ClientData;
1958
1959static int
Fred Drake509d79a2000-07-08 04:04:38 +00001960PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001961{
1962 errorInCmd = 1;
1963 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1964 LEAVE_PYTHON
1965 return TCL_ERROR;
1966}
1967
Guido van Rossum18468821994-06-20 07:49:28 +00001968/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001969 * function or method.
1970 */
Guido van Rossum18468821994-06-20 07:49:28 +00001971static int
Fred Drake509d79a2000-07-08 04:04:38 +00001972PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001973{
Guido van Rossum00d93061998-05-28 23:06:38 +00001974 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001975 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001976 int i, rv;
1977 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001978
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001979 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001980
Barry Warsawfa701a81997-01-16 00:15:11 +00001981 /* TBD: no error checking here since we know, via the
1982 * Tkapp_CreateCommand() that the client data is a two-tuple
1983 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001984 self = data->self;
1985 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001986
Barry Warsawfa701a81997-01-16 00:15:11 +00001987 /* Create argument list (argv1, ..., argvN) */
1988 if (!(arg = PyTuple_New(argc - 1)))
1989 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001990
Barry Warsawfa701a81997-01-16 00:15:11 +00001991 for (i = 0; i < (argc - 1); i++) {
1992 PyObject *s = PyString_FromString(argv[i + 1]);
1993 if (!s || PyTuple_SetItem(arg, i, s)) {
1994 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001995 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001996 }
1997 }
1998 res = PyEval_CallObject(func, arg);
1999 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002000
Barry Warsawfa701a81997-01-16 00:15:11 +00002001 if (res == NULL)
2002 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002003
Barry Warsawfa701a81997-01-16 00:15:11 +00002004 if (!(tmp = PyList_New(0))) {
2005 Py_DECREF(res);
2006 return PythonCmd_Error(interp);
2007 }
2008
Guido van Rossum2834b972000-10-06 16:58:26 +00002009 s = AsString(res, tmp);
2010 if (s == NULL) {
2011 rv = PythonCmd_Error(interp);
2012 }
2013 else {
2014 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
2015 rv = TCL_OK;
2016 }
2017
Barry Warsawfa701a81997-01-16 00:15:11 +00002018 Py_DECREF(res);
2019 Py_DECREF(tmp);
2020
Guido van Rossum00d93061998-05-28 23:06:38 +00002021 LEAVE_PYTHON
2022
Guido van Rossum2834b972000-10-06 16:58:26 +00002023 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002024}
2025
2026static void
Fred Drake509d79a2000-07-08 04:04:38 +00002027PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002028{
Guido van Rossum00d93061998-05-28 23:06:38 +00002029 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2030
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002031 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002032 Py_XDECREF(data->self);
2033 Py_XDECREF(data->func);
2034 PyMem_DEL(data);
2035 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002036}
2037
Barry Warsawfa701a81997-01-16 00:15:11 +00002038
2039
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002040
2041TCL_DECLARE_MUTEX(command_mutex)
2042
2043typedef struct CommandEvent{
2044 Tcl_Event ev;
2045 Tcl_Interp* interp;
2046 char *name;
2047 int create;
2048 int *status;
2049 ClientData *data;
2050 Tcl_Condition done;
2051} CommandEvent;
2052
2053static int
2054Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002055{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002056 if (ev->create)
2057 *ev->status = Tcl_CreateCommand(
2058 ev->interp, ev->name, PythonCmd,
2059 ev->data, PythonCmdDelete) == NULL;
2060 else
2061 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2062 Tcl_MutexLock(&command_mutex);
2063 Tcl_ConditionNotify(&ev->done);
2064 Tcl_MutexUnlock(&command_mutex);
2065 return 1;
2066}
2067
2068static PyObject *
2069Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2070{
2071 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002072 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002073 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002074 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002075 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002076
Guido van Rossum43713e52000-02-29 13:59:29 +00002077 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002078 return NULL;
2079 if (!PyCallable_Check(func)) {
2080 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002081 return NULL;
2082 }
Guido van Rossum18468821994-06-20 07:49:28 +00002083
Martin v. Löwisa9656492003-03-30 08:44:58 +00002084#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002085 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002086 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002087 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002088#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002089
Guido van Rossum00d93061998-05-28 23:06:38 +00002090 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002091 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002092 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002093 Py_XINCREF(self);
2094 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002095 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002096 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002097
2098 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2099 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2100 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2101 ev->interp = self->interp;
2102 ev->create = 1;
2103 ev->name = cmdName;
2104 ev->data = (ClientData)data;
2105 ev->status = &err;
2106 ev->done = NULL;
2107 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2108 }
2109 else {
2110 ENTER_TCL
2111 err = Tcl_CreateCommand(
2112 Tkapp_Interp(self), cmdName, PythonCmd,
2113 (ClientData)data, PythonCmdDelete) == NULL;
2114 LEAVE_TCL
2115 }
2116 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002117 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002118 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002119 return NULL;
2120 }
Guido van Rossum18468821994-06-20 07:49:28 +00002121
Barry Warsawfa701a81997-01-16 00:15:11 +00002122 Py_INCREF(Py_None);
2123 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002124}
2125
Barry Warsawfa701a81997-01-16 00:15:11 +00002126
2127
Guido van Rossum18468821994-06-20 07:49:28 +00002128static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002129Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002130{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002131 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002132 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002133 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002134
Guido van Rossum43713e52000-02-29 13:59:29 +00002135 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002136 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002137 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2138 CommandEvent *ev;
2139 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2140 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2141 ev->interp = self->interp;
2142 ev->create = 0;
2143 ev->name = cmdName;
2144 ev->status = &err;
2145 ev->done = NULL;
2146 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2147 &command_mutex);
2148 }
2149 else {
2150 ENTER_TCL
2151 err = Tcl_DeleteCommand(self->interp, cmdName);
2152 LEAVE_TCL
2153 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002154 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002155 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2156 return NULL;
2157 }
2158 Py_INCREF(Py_None);
2159 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002160}
2161
Barry Warsawfa701a81997-01-16 00:15:11 +00002162
2163
Guido van Rossum00d93061998-05-28 23:06:38 +00002164#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002165/** File Handler **/
2166
Guido van Rossum00d93061998-05-28 23:06:38 +00002167typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002168 PyObject *func;
2169 PyObject *file;
2170 int id;
2171 struct _fhcdata *next;
2172} FileHandler_ClientData;
2173
2174static FileHandler_ClientData *HeadFHCD;
2175
2176static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002177NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002178{
2179 FileHandler_ClientData *p;
2180 p = PyMem_NEW(FileHandler_ClientData, 1);
2181 if (p != NULL) {
2182 Py_XINCREF(func);
2183 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002184 p->func = func;
2185 p->file = file;
2186 p->id = id;
2187 p->next = HeadFHCD;
2188 HeadFHCD = p;
2189 }
2190 return p;
2191}
2192
2193static void
Fred Drake509d79a2000-07-08 04:04:38 +00002194DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002195{
2196 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002197
2198 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002199 while ((p = *pp) != NULL) {
2200 if (p->id == id) {
2201 *pp = p->next;
2202 Py_XDECREF(p->func);
2203 Py_XDECREF(p->file);
2204 PyMem_DEL(p);
2205 }
2206 else
2207 pp = &p->next;
2208 }
2209}
2210
Guido van Rossuma597dde1995-01-10 20:56:29 +00002211static void
Fred Drake509d79a2000-07-08 04:04:38 +00002212FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002213{
Guido van Rossum00d93061998-05-28 23:06:38 +00002214 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002215 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002216
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002217 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002218 func = data->func;
2219 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002220
Barry Warsawfa701a81997-01-16 00:15:11 +00002221 arg = Py_BuildValue("(Oi)", file, (long) mask);
2222 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002223 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002224
2225 if (res == NULL) {
2226 errorInCmd = 1;
2227 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2228 }
2229 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002230 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002231}
2232
Guido van Rossum18468821994-06-20 07:49:28 +00002233static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002234Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2235 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002236{
Guido van Rossum00d93061998-05-28 23:06:38 +00002237 FileHandler_ClientData *data;
2238 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002239 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002240
Guido van Rossum2834b972000-10-06 16:58:26 +00002241 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2242 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002243 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002244
Martin v. Löwisa9656492003-03-30 08:44:58 +00002245#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002246 if (!self && !tcl_lock) {
2247 /* We don't have the Tcl lock since Tcl is threaded. */
2248 PyErr_SetString(PyExc_RuntimeError,
2249 "_tkinter.createfilehandler not supported "
2250 "for threaded Tcl");
2251 return NULL;
2252 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002253#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002254
2255 if (self) {
2256 CHECK_TCL_APPARTMENT;
2257 }
2258
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002259 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002260 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002261 return NULL;
2262 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002263 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002264 return NULL;
2265 }
2266
Guido van Rossuma80649b2000-03-28 20:07:05 +00002267 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002268 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002269 return NULL;
2270
Barry Warsawfa701a81997-01-16 00:15:11 +00002271 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002272 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002273 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002274 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002275 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002276 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002277}
2278
2279static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002280Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002281{
Barry Warsawfa701a81997-01-16 00:15:11 +00002282 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002283 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002284
Guido van Rossum43713e52000-02-29 13:59:29 +00002285 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002286 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002287
Martin v. Löwisa9656492003-03-30 08:44:58 +00002288#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002289 if (!self && !tcl_lock) {
2290 /* We don't have the Tcl lock since Tcl is threaded. */
2291 PyErr_SetString(PyExc_RuntimeError,
2292 "_tkinter.deletefilehandler not supported "
2293 "for threaded Tcl");
2294 return NULL;
2295 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002296#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002297
2298 if (self) {
2299 CHECK_TCL_APPARTMENT;
2300 }
2301
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002302 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002303 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002304 return NULL;
2305
Guido van Rossuma80649b2000-03-28 20:07:05 +00002306 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002307
Barry Warsawfa701a81997-01-16 00:15:11 +00002308 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002309 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002310 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002311 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002312 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002313 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002314}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002315#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002316
Barry Warsawfa701a81997-01-16 00:15:11 +00002317
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002318/**** Tktt Object (timer token) ****/
2319
Jeremy Hylton938ace62002-07-17 16:30:39 +00002320static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002321
Guido van Rossum00d93061998-05-28 23:06:38 +00002322typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002323 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002324 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002325 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002326} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002327
2328static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002329Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002330{
Barry Warsawfa701a81997-01-16 00:15:11 +00002331 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002332 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002333
Guido van Rossum43713e52000-02-29 13:59:29 +00002334 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002335 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002336 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002337 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002338 v->token = NULL;
2339 }
2340 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002341 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002342 Py_DECREF(func);
2343 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002344 }
2345 Py_INCREF(Py_None);
2346 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002347}
2348
2349static PyMethodDef Tktt_methods[] =
2350{
Neal Norwitzb0493252002-03-31 14:44:22 +00002351 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002352 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002353};
2354
2355static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002356Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002357{
Barry Warsawfa701a81997-01-16 00:15:11 +00002358 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002359
Guido van Rossumb18618d2000-05-03 23:44:39 +00002360 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002361 if (v == NULL)
2362 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002363
Guido van Rossum00d93061998-05-28 23:06:38 +00002364 Py_INCREF(func);
2365 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002366 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002367
2368 /* Extra reference, deleted when called or when handler is deleted */
2369 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002370 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002371}
2372
2373static void
Fred Drake509d79a2000-07-08 04:04:38 +00002374Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002375{
Guido van Rossum00d93061998-05-28 23:06:38 +00002376 TkttObject *v = (TkttObject *)self;
2377 PyObject *func = v->func;
2378
2379 Py_XDECREF(func);
2380
Guido van Rossumb18618d2000-05-03 23:44:39 +00002381 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002382}
2383
Guido van Rossum597ac201998-05-12 14:36:19 +00002384static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002385Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002386{
Barry Warsawfa701a81997-01-16 00:15:11 +00002387 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002388 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002389
Tim Peters885d4572001-11-28 20:27:42 +00002390 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002391 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002392 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002393}
2394
2395static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002396Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002397{
Barry Warsawfa701a81997-01-16 00:15:11 +00002398 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002399}
2400
2401static PyTypeObject Tktt_Type =
2402{
Guido van Rossum35d43371997-08-02 00:09:09 +00002403 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002404 0, /*ob_size */
2405 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002406 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002407 0, /*tp_itemsize */
2408 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002409 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002410 Tktt_GetAttr, /*tp_getattr */
2411 0, /*tp_setattr */
2412 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002413 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002414 0, /*tp_as_number */
2415 0, /*tp_as_sequence */
2416 0, /*tp_as_mapping */
2417 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002418};
2419
Barry Warsawfa701a81997-01-16 00:15:11 +00002420
2421
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002422/** Timer Handler **/
2423
2424static void
Fred Drake509d79a2000-07-08 04:04:38 +00002425TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002426{
Guido van Rossum00d93061998-05-28 23:06:38 +00002427 TkttObject *v = (TkttObject *)clientData;
2428 PyObject *func = v->func;
2429 PyObject *res;
2430
2431 if (func == NULL)
2432 return;
2433
2434 v->func = NULL;
2435
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002436 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002437
2438 res = PyEval_CallObject(func, NULL);
2439 Py_DECREF(func);
2440 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002441
Barry Warsawfa701a81997-01-16 00:15:11 +00002442 if (res == NULL) {
2443 errorInCmd = 1;
2444 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2445 }
2446 else
2447 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002448
2449 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002450}
2451
2452static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002453Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002454{
Barry Warsawfa701a81997-01-16 00:15:11 +00002455 int milliseconds;
2456 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002457 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002458
Guido van Rossum2834b972000-10-06 16:58:26 +00002459 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2460 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002461 return NULL;
2462 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002463 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002464 return NULL;
2465 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002466
Martin v. Löwisa9656492003-03-30 08:44:58 +00002467#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002468 if (!self && !tcl_lock) {
2469 /* We don't have the Tcl lock since Tcl is threaded. */
2470 PyErr_SetString(PyExc_RuntimeError,
2471 "_tkinter.createtimerhandler not supported "
2472 "for threaded Tcl");
2473 return NULL;
2474 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002475#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002476
2477 if (self) {
2478 CHECK_TCL_APPARTMENT;
2479 }
2480
Guido van Rossum00d93061998-05-28 23:06:38 +00002481 v = Tktt_New(func);
2482 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2483 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002484
Guido van Rossum00d93061998-05-28 23:06:38 +00002485 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002486}
2487
Barry Warsawfa701a81997-01-16 00:15:11 +00002488
Guido van Rossum18468821994-06-20 07:49:28 +00002489/** Event Loop **/
2490
Guido van Rossum18468821994-06-20 07:49:28 +00002491static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002492Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002493{
Barry Warsawfa701a81997-01-16 00:15:11 +00002494 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002495 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002496#ifdef WITH_THREAD
2497 PyThreadState *tstate = PyThreadState_Get();
2498#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002499
Guido van Rossum43713e52000-02-29 13:59:29 +00002500 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002501 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002502
Martin v. Löwisa9656492003-03-30 08:44:58 +00002503#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002504 if (!self && !tcl_lock) {
2505 /* We don't have the Tcl lock since Tcl is threaded. */
2506 PyErr_SetString(PyExc_RuntimeError,
2507 "_tkinter.mainloop not supported "
2508 "for threaded Tcl");
2509 return NULL;
2510 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002511#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002512
2513 if (self) {
2514 CHECK_TCL_APPARTMENT;
2515 self->dispatching = 1;
2516 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002517
Barry Warsawfa701a81997-01-16 00:15:11 +00002518 quitMainLoop = 0;
2519 while (Tk_GetNumMainWindows() > threshold &&
2520 !quitMainLoop &&
2521 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002522 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002523 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002524
2525#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002526 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002527 /* Allow other Python threads to run. */
2528 ENTER_TCL
2529 result = Tcl_DoOneEvent(0);
2530 LEAVE_TCL
2531 }
2532 else {
2533 Py_BEGIN_ALLOW_THREADS
2534 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2535 tcl_tstate = tstate;
2536 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2537 tcl_tstate = NULL;
2538 if(tcl_lock)PyThread_release_lock(tcl_lock);
2539 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002540 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002541 Py_END_ALLOW_THREADS
2542 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002543#else
2544 result = Tcl_DoOneEvent(0);
2545#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002546
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002547 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002548 if (self)
2549 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002550 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002551 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002552 if (result < 0)
2553 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002554 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002555 if (self)
2556 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002557 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002558
Barry Warsawfa701a81997-01-16 00:15:11 +00002559 if (errorInCmd) {
2560 errorInCmd = 0;
2561 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2562 excInCmd = valInCmd = trbInCmd = NULL;
2563 return NULL;
2564 }
2565 Py_INCREF(Py_None);
2566 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002567}
2568
2569static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002570Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002571{
Guido van Rossum35d43371997-08-02 00:09:09 +00002572 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002573 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002574
Guido van Rossum43713e52000-02-29 13:59:29 +00002575 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002576 return NULL;
2577
Guido van Rossum00d93061998-05-28 23:06:38 +00002578 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002579 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002580 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002581 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002582}
2583
2584static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002585Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002586{
2587
Guido van Rossum43713e52000-02-29 13:59:29 +00002588 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002589 return NULL;
2590
2591 quitMainLoop = 1;
2592 Py_INCREF(Py_None);
2593 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002594}
2595
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002596static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002597Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002598{
2599
Guido van Rossum43713e52000-02-29 13:59:29 +00002600 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002601 return NULL;
2602
2603 return PyInt_FromLong((long)Tkapp_Interp(self));
2604}
2605
Barry Warsawfa701a81997-01-16 00:15:11 +00002606
Martin v. Löwisffad6332002-11-26 09:28:05 +00002607static PyObject *
2608Tkapp_WantObjects(PyObject *self, PyObject *args)
2609{
2610
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002611 int wantobjects = -1;
2612 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002613 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002614 if (wantobjects == -1)
2615 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002616 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002617
2618 Py_INCREF(Py_None);
2619 return Py_None;
2620}
2621
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002622static PyObject *
2623Tkapp_WillDispatch(PyObject *self, PyObject *args)
2624{
2625
2626 ((TkappObject*)self)->dispatching = 1;
2627
2628 Py_INCREF(Py_None);
2629 return Py_None;
2630}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002631
Barry Warsawfa701a81997-01-16 00:15:11 +00002632
Guido van Rossum18468821994-06-20 07:49:28 +00002633/**** Tkapp Method List ****/
2634
2635static PyMethodDef Tkapp_methods[] =
2636{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002637 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002638 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002639 {"call", Tkapp_Call, METH_OLDARGS},
2640 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2641 {"eval", Tkapp_Eval, METH_VARARGS},
2642 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2643 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2644 {"record", Tkapp_Record, METH_VARARGS},
2645 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2646 {"setvar", Tkapp_SetVar, METH_VARARGS},
2647 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2648 {"getvar", Tkapp_GetVar, METH_VARARGS},
2649 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2650 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2651 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2652 {"getint", Tkapp_GetInt, METH_VARARGS},
2653 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2654 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2655 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2656 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2657 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2658 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2659 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2660 {"split", Tkapp_Split, METH_VARARGS},
2661 {"merge", Tkapp_Merge, METH_OLDARGS},
2662 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2663 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002664#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002665 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2666 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002667#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002668 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2669 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2670 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2671 {"quit", Tkapp_Quit, METH_VARARGS},
2672 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002673 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002674};
2675
Barry Warsawfa701a81997-01-16 00:15:11 +00002676
2677
Guido van Rossum18468821994-06-20 07:49:28 +00002678/**** Tkapp Type Methods ****/
2679
2680static void
Fred Drake509d79a2000-07-08 04:04:38 +00002681Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002682{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002683 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002684 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002685 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002686 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002687 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002688 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002689}
2690
2691static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002692Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002693{
Guido van Rossum35d43371997-08-02 00:09:09 +00002694 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002695}
2696
2697static PyTypeObject Tkapp_Type =
2698{
Guido van Rossum35d43371997-08-02 00:09:09 +00002699 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002700 0, /*ob_size */
2701 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002702 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002703 0, /*tp_itemsize */
2704 Tkapp_Dealloc, /*tp_dealloc */
2705 0, /*tp_print */
2706 Tkapp_GetAttr, /*tp_getattr */
2707 0, /*tp_setattr */
2708 0, /*tp_compare */
2709 0, /*tp_repr */
2710 0, /*tp_as_number */
2711 0, /*tp_as_sequence */
2712 0, /*tp_as_mapping */
2713 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002714};
2715
Barry Warsawfa701a81997-01-16 00:15:11 +00002716
2717
Guido van Rossum18468821994-06-20 07:49:28 +00002718/**** Tkinter Module ****/
2719
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002720typedef struct {
2721 PyObject* tuple;
2722 int size; /* current size */
2723 int maxsize; /* allocated size */
2724} FlattenContext;
2725
2726static int
2727_bump(FlattenContext* context, int size)
2728{
Guido van Rossum2834b972000-10-06 16:58:26 +00002729 /* expand tuple to hold (at least) size new items.
2730 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002731
2732 int maxsize = context->maxsize * 2;
2733
2734 if (maxsize < context->size + size)
2735 maxsize = context->size + size;
2736
2737 context->maxsize = maxsize;
2738
Tim Peters4324aa32001-05-28 22:30:08 +00002739 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002740}
2741
2742static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002743_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002744{
2745 /* add tuple or list to argument tuple (recursively) */
2746
2747 int i, size;
2748
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002749 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002750 PyErr_SetString(PyExc_ValueError,
2751 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002752 return 0;
2753 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002754 size = PyList_GET_SIZE(item);
2755 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002756 if (context->size + size > context->maxsize &&
2757 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002758 return 0;
2759 /* copy items to output tuple */
2760 for (i = 0; i < size; i++) {
2761 PyObject *o = PyList_GET_ITEM(item, i);
2762 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002763 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002764 return 0;
2765 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002766 if (context->size + 1 > context->maxsize &&
2767 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002768 return 0;
2769 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002770 PyTuple_SET_ITEM(context->tuple,
2771 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002772 }
2773 }
2774 } else if (PyTuple_Check(item)) {
2775 /* same, for tuples */
2776 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002777 if (context->size + size > context->maxsize &&
2778 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002779 return 0;
2780 for (i = 0; i < size; i++) {
2781 PyObject *o = PyTuple_GET_ITEM(item, i);
2782 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002783 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002784 return 0;
2785 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002786 if (context->size + 1 > context->maxsize &&
2787 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002788 return 0;
2789 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002790 PyTuple_SET_ITEM(context->tuple,
2791 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002792 }
2793 }
2794 } else {
2795 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2796 return 0;
2797 }
2798 return 1;
2799}
2800
2801static PyObject *
2802Tkinter_Flatten(PyObject* self, PyObject* args)
2803{
2804 FlattenContext context;
2805 PyObject* item;
2806
2807 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2808 return NULL;
2809
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002810 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002811 if (context.maxsize <= 0)
2812 return PyTuple_New(0);
2813
2814 context.tuple = PyTuple_New(context.maxsize);
2815 if (!context.tuple)
2816 return NULL;
2817
2818 context.size = 0;
2819
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002820 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002821 return NULL;
2822
Tim Peters4324aa32001-05-28 22:30:08 +00002823 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002824 return NULL;
2825
2826 return context.tuple;
2827}
2828
Guido van Rossum18468821994-06-20 07:49:28 +00002829static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002830Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002831{
Barry Warsawfa701a81997-01-16 00:15:11 +00002832 char *screenName = NULL;
2833 char *baseName = NULL;
2834 char *className = NULL;
2835 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002836 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002837
Guido van Rossum35d43371997-08-02 00:09:09 +00002838 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002839 if (baseName != NULL)
2840 baseName++;
2841 else
2842 baseName = Py_GetProgramName();
2843 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002844
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002845 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002846 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002847 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002848 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002849
Barry Warsawfa701a81997-01-16 00:15:11 +00002850 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002851 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002852}
2853
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002854static PyObject *
2855Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2856{
2857 int new_val;
2858 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2859 return NULL;
2860 if (new_val < 0) {
2861 PyErr_SetString(PyExc_ValueError,
2862 "busywaitinterval must be >= 0");
2863 return NULL;
2864 }
2865 Tkinter_busywaitinterval = new_val;
2866 Py_INCREF(Py_None);
2867 return Py_None;
2868}
2869
2870static char setbusywaitinterval_doc[] =
2871"setbusywaitinterval(n) -> None\n\
2872\n\
2873Set the busy-wait interval in milliseconds between successive\n\
2874calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2875It should be set to a divisor of the maximum time between\n\
2876frames in an animation.";
2877
2878static PyObject *
2879Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2880{
2881 return PyInt_FromLong(Tkinter_busywaitinterval);
2882}
2883
2884static char getbusywaitinterval_doc[] =
2885"getbusywaitinterval() -> int\n\
2886\n\
2887Return the current busy-wait interval between successive\n\
2888calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2889
Guido van Rossum18468821994-06-20 07:49:28 +00002890static PyMethodDef moduleMethods[] =
2891{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002892 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2893 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002894#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002895 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2896 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002897#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002898 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2899 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2900 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2901 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002902 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2903 setbusywaitinterval_doc},
2904 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2905 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002906 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002907};
2908
Guido van Rossum7bf15641998-05-22 18:28:17 +00002909#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002910
2911static int stdin_ready = 0;
2912
Guido van Rossumad4db171998-06-13 13:56:28 +00002913#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002914static void
Fred Drake509d79a2000-07-08 04:04:38 +00002915MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002916{
2917 stdin_ready = 1;
2918}
Guido van Rossumad4db171998-06-13 13:56:28 +00002919#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002920
Martin v. Löwisa9656492003-03-30 08:44:58 +00002921#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002922static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002923#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002924
Guido van Rossum18468821994-06-20 07:49:28 +00002925static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002926EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002927{
Guido van Rossumad4db171998-06-13 13:56:28 +00002928#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002929 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002930#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002931#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002932 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002933#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002934 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002935 errorInCmd = 0;
2936#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002937 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002938 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002939#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002940 while (!errorInCmd && !stdin_ready) {
2941 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002942#ifdef MS_WINDOWS
2943 if (_kbhit()) {
2944 stdin_ready = 1;
2945 break;
2946 }
2947#endif
2948#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002949 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002950 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002951 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002952
Guido van Rossum00d93061998-05-28 23:06:38 +00002953 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002954
2955 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002956 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002957 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002958 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002959 Py_END_ALLOW_THREADS
2960#else
2961 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002962#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002963
2964 if (result < 0)
2965 break;
2966 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002967#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002968 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002969#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002970 if (errorInCmd) {
2971 errorInCmd = 0;
2972 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2973 excInCmd = valInCmd = trbInCmd = NULL;
2974 PyErr_Print();
2975 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002976#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002977 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002978#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002979 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002980}
Guido van Rossum18468821994-06-20 07:49:28 +00002981
Guido van Rossum00d93061998-05-28 23:06:38 +00002982#endif
2983
Guido van Rossum7bf15641998-05-22 18:28:17 +00002984static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002985EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002986{
Guido van Rossum00d93061998-05-28 23:06:38 +00002987#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002988 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002989#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002990 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002991#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002992 PyOS_InputHook = EventHook;
2993 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002994#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002995}
2996
2997static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002998DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002999{
Guido van Rossum00d93061998-05-28 23:06:38 +00003000#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003001 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3002 PyOS_InputHook = NULL;
3003 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003004#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003005}
3006
Barry Warsawfa701a81997-01-16 00:15:11 +00003007
3008/* all errors will be checked in one fell swoop in init_tkinter() */
3009static void
Fred Drake509d79a2000-07-08 04:04:38 +00003010ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003011{
3012 PyObject *v = PyInt_FromLong(val);
3013 if (v) {
3014 PyDict_SetItemString(d, name, v);
3015 Py_DECREF(v);
3016 }
3017}
3018static void
Fred Drake509d79a2000-07-08 04:04:38 +00003019ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003020{
3021 PyObject *v = PyString_FromString(val);
3022 if (v) {
3023 PyDict_SetItemString(d, name, v);
3024 Py_DECREF(v);
3025 }
3026}
3027
3028
Mark Hammond62b1ab12002-07-23 06:31:15 +00003029PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003030init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003031{
Barry Warsawfa701a81997-01-16 00:15:11 +00003032 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003033
Barry Warsawfa701a81997-01-16 00:15:11 +00003034 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003035
3036#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003037 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003038#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003039
Barry Warsawfa701a81997-01-16 00:15:11 +00003040 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00003041
Barry Warsawfa701a81997-01-16 00:15:11 +00003042 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003043 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003044 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003045
Guido van Rossum35d43371997-08-02 00:09:09 +00003046 ins_long(d, "READABLE", TCL_READABLE);
3047 ins_long(d, "WRITABLE", TCL_WRITABLE);
3048 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3049 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3050 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3051 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3052 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3053 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3054 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003055 ins_string(d, "TK_VERSION", TK_VERSION);
3056 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003057
Guido van Rossum83551bf1997-09-13 00:44:23 +00003058 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003059
3060 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003061 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3062
Martin v. Löwisffad6332002-11-26 09:28:05 +00003063 PyTclObject_Type.ob_type = &PyType_Type;
3064 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003065
3066#ifdef TK_AQUA
3067 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3068 * start waking up. Note that Tcl_FindExecutable will do this, this
3069 * code must be above it! The original warning from
3070 * tkMacOSXAppInit.c is copied below.
3071 *
3072 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3073 * Tcl interpreter for now. It probably should work to do this
3074 * in the other order, but for now it doesn't seem to.
3075 *
3076 */
3077 Tk_MacOSXSetupTkNotifier();
3078#endif
3079
3080
Guido van Rossume187b0e2000-03-27 21:46:29 +00003081 /* This helps the dynamic loader; in Unicode aware Tcl versions
3082 it also helps Tcl find its encodings. */
3083 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003084
Barry Warsawfa701a81997-01-16 00:15:11 +00003085 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003086 return;
3087
Guido van Rossum43ff8681998-07-14 18:02:13 +00003088#if 0
3089 /* This was not a good idea; through <Destroy> bindings,
3090 Tcl_Finalize() may invoke Python code but at that point the
3091 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003092 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003093#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003094
Jack Jansen34cc5c31995-10-31 16:15:12 +00003095#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003096 /*
3097 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
3098 ** Most of the initializations in that routine (toolbox init calls and
3099 ** such) have already been done for us, so we only need these.
3100 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003101 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003102
3103 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00003104#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00003105 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00003106#endif /* GENERATINGCFM */
3107#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00003108}
Guido van Rossum9722ad81995-09-22 23:49:28 +00003109
Guido van Rossumec22c921996-02-25 04:50:29 +00003110
Barry Warsawfa701a81997-01-16 00:15:11 +00003111
Guido van Rossum9722ad81995-09-22 23:49:28 +00003112#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003113
3114/*
Guido van Rossumec22c921996-02-25 04:50:29 +00003115** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003116*/
3117
Guido van Rossum9722ad81995-09-22 23:49:28 +00003118void
3119panic(char * format, ...)
3120{
Barry Warsawfa701a81997-01-16 00:15:11 +00003121 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003122
Barry Warsawfa701a81997-01-16 00:15:11 +00003123 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003124
Guido van Rossum227cf761998-08-05 13:53:32 +00003125 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00003126 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003127
Barry Warsawfa701a81997-01-16 00:15:11 +00003128 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003129
Barry Warsawfa701a81997-01-16 00:15:11 +00003130 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00003131}
Jack Jansen40b546d1995-11-14 10:34:45 +00003132
Guido van Rossumec22c921996-02-25 04:50:29 +00003133/*
3134** Pass events to SIOUX before passing them to Tk.
3135*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003136
Guido van Rossumec22c921996-02-25 04:50:29 +00003137static int
Fred Drake509d79a2000-07-08 04:04:38 +00003138PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003139{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003140 WindowPtr frontwin;
3141 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00003142 ** Sioux eats too many events, so we don't pass it everything. We
3143 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003144 ** the Sioux window is frontmost. This means that Tk menus don't work
3145 ** in that case, but at least we can scroll the sioux window.
3146 ** Note that the SIOUXIsAppWindow() routine we use here is not really
3147 ** part of the external interface of Sioux...
3148 */
3149 frontwin = FrontWindow();
3150 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
3151 if (SIOUXHandleOneEvent(eventPtr))
3152 return 0; /* Nothing happened to the Tcl event queue */
3153 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003154 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003155}
3156
Guido van Rossumec22c921996-02-25 04:50:29 +00003157#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003158
3159/*
3160** Additional Mac specific code for dealing with shared libraries.
3161*/
3162
3163#include <Resources.h>
3164#include <CodeFragments.h>
3165
3166static int loaded_from_shlib = 0;
3167static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003168
Jack Jansen34cc5c31995-10-31 16:15:12 +00003169/*
3170** If this module is dynamically loaded the following routine should
3171** be the init routine. It takes care of adding the shared library to
3172** the resource-file chain, so that the tk routines can find their
3173** resources.
3174*/
3175OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003176init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003177{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00003178 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00003179 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003180 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003181 library_fss = *data->fragLocator.u.onDisk.fileSpec;
3182 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003183 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003184 library_fss = *data->fragLocator.u.inSegs.fileSpec;
3185 loaded_from_shlib = 1;
3186 }
3187 return noErr;
3188}
3189
3190/*
3191** Insert the library resources into the search path. Put them after
3192** the resources from the application. Again, we ignore errors.
3193*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003194static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003195mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003196{
3197 if ( !loaded_from_shlib )
3198 return;
3199 (void)FSpOpenResFile(&library_fss, fsRdPerm);
3200}
3201
Guido van Rossumec22c921996-02-25 04:50:29 +00003202#endif /* GENERATINGCFM */
3203#endif /* macintosh */