blob: fbc6ec10c9b69d05f1a0e3cde460225c2a1c0eb0 [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öwis8fd86cc2003-05-19 19:57:42 +00001650 if (((TkappObject*)self)->wantobjects) {
1651 res = FromObj(self, tres);
1652 }
1653 else {
1654 res = PyString_FromString(Tcl_GetString(tres));
1655 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001656 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001657 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001658}
1659
1660static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001661Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001662{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001663 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001664}
1665
1666static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001667Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001668{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001669 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001670}
1671
Barry Warsawfa701a81997-01-16 00:15:11 +00001672
1673
Guido van Rossum18468821994-06-20 07:49:28 +00001674static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001675UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001676{
Guido van Rossum35d43371997-08-02 00:09:09 +00001677 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001678 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001679 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001680
Guido van Rossum43713e52000-02-29 13:59:29 +00001681 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001682 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001683
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001684 ENTER_TCL
1685 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1686 ENTER_OVERLAP
1687 if (code == TCL_ERROR)
1688 res = Tkinter_Error(self);
1689 else {
1690 Py_INCREF(Py_None);
1691 res = Py_None;
1692 }
1693 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001694 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001695}
1696
1697static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001698Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001699{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001700 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001701}
1702
1703static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001704Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001705{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001706 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001707}
1708
Barry Warsawfa701a81997-01-16 00:15:11 +00001709
1710
Guido van Rossum18468821994-06-20 07:49:28 +00001711/** Tcl to Python **/
1712
1713static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001714Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001715{
Barry Warsawfa701a81997-01-16 00:15:11 +00001716 char *s;
1717 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001718
Martin v. Löwisffad6332002-11-26 09:28:05 +00001719 if (PyTuple_Size(args) == 1) {
1720 PyObject* o = PyTuple_GetItem(args, 0);
1721 if (PyInt_Check(o)) {
1722 Py_INCREF(o);
1723 return o;
1724 }
1725 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001726 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001727 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001728 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001729 return Tkinter_Error(self);
1730 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001731}
1732
1733static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001734Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001735{
Barry Warsawfa701a81997-01-16 00:15:11 +00001736 char *s;
1737 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001738
Martin v. Löwisffad6332002-11-26 09:28:05 +00001739 if (PyTuple_Size(args) == 1) {
1740 PyObject *o = PyTuple_GetItem(args, 0);
1741 if (PyFloat_Check(o)) {
1742 Py_INCREF(o);
1743 return o;
1744 }
1745 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001746 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001747 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001748 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001749 return Tkinter_Error(self);
1750 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001751}
1752
1753static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001754Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001755{
Barry Warsawfa701a81997-01-16 00:15:11 +00001756 char *s;
1757 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001758
Martin v. Löwisffad6332002-11-26 09:28:05 +00001759 if (PyTuple_Size(args) == 1) {
1760 PyObject *o = PyTuple_GetItem(args, 0);
1761 if (PyInt_Check(o)) {
1762 Py_INCREF(o);
1763 return o;
1764 }
1765 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001766 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001767 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001768 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1769 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001770 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001771}
1772
1773static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001774Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001775{
Barry Warsawfa701a81997-01-16 00:15:11 +00001776 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001777 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001778 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001779
Guido van Rossum43713e52000-02-29 13:59:29 +00001780 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001781 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001782
1783 CHECK_TCL_APPARTMENT;
1784
Guido van Rossum00d93061998-05-28 23:06:38 +00001785 ENTER_TCL
1786 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001787 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001788 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001789 res = Tkinter_Error(self);
1790 else
1791 res = Py_BuildValue("s", Tkapp_Result(self));
1792 LEAVE_OVERLAP_TCL
1793 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001794}
1795
1796static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001797Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001798{
Barry Warsawfa701a81997-01-16 00:15:11 +00001799 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001800 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001801 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001802 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001803
Guido van Rossum43713e52000-02-29 13:59:29 +00001804 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001805 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001806
1807 CHECK_TCL_APPARTMENT;
1808
Guido van Rossum00d93061998-05-28 23:06:38 +00001809 ENTER_TCL
1810 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001811 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001812 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001813 res = Tkinter_Error(self);
1814 else
1815 res = Py_BuildValue("l", v);
1816 LEAVE_OVERLAP_TCL
1817 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001818}
1819
1820static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001821Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001822{
Barry Warsawfa701a81997-01-16 00:15:11 +00001823 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001824 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001825 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001826 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001827
Guido van Rossum43713e52000-02-29 13:59:29 +00001828 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001829 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001830 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001831 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001832 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001833 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001834 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001835 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001836 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001837 res = Tkinter_Error(self);
1838 else
1839 res = Py_BuildValue("d", v);
1840 LEAVE_OVERLAP_TCL
1841 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001842}
1843
1844static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001845Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001846{
Barry Warsawfa701a81997-01-16 00:15:11 +00001847 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001848 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001849 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001850 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001851
Guido van Rossum43713e52000-02-29 13:59:29 +00001852 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001853 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001854 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001855 ENTER_TCL
1856 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001857 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001858 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001859 res = Tkinter_Error(self);
1860 else
1861 res = Py_BuildValue("i", v);
1862 LEAVE_OVERLAP_TCL
1863 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001864}
1865
Barry Warsawfa701a81997-01-16 00:15:11 +00001866
1867
Guido van Rossum18468821994-06-20 07:49:28 +00001868static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001869Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001870{
Barry Warsawfa701a81997-01-16 00:15:11 +00001871 char *list;
1872 int argc;
1873 char **argv;
1874 PyObject *v;
1875 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001876
Martin v. Löwisffad6332002-11-26 09:28:05 +00001877 if (PyTuple_Size(args) == 1) {
1878 v = PyTuple_GetItem(args, 0);
1879 if (PyTuple_Check(v)) {
1880 Py_INCREF(v);
1881 return v;
1882 }
1883 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001884 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001885 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001886
Barry Warsawfa701a81997-01-16 00:15:11 +00001887 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1888 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001889
Barry Warsawfa701a81997-01-16 00:15:11 +00001890 if (!(v = PyTuple_New(argc)))
1891 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001892
Barry Warsawfa701a81997-01-16 00:15:11 +00001893 for (i = 0; i < argc; i++) {
1894 PyObject *s = PyString_FromString(argv[i]);
1895 if (!s || PyTuple_SetItem(v, i, s)) {
1896 Py_DECREF(v);
1897 v = NULL;
1898 goto finally;
1899 }
1900 }
Guido van Rossum18468821994-06-20 07:49:28 +00001901
Barry Warsawfa701a81997-01-16 00:15:11 +00001902 finally:
1903 ckfree(FREECAST argv);
1904 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001905}
1906
1907static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001908Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001909{
Barry Warsawfa701a81997-01-16 00:15:11 +00001910 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001911
Martin v. Löwisffad6332002-11-26 09:28:05 +00001912 if (PyTuple_Size(args) == 1) {
1913 PyObject* o = PyTuple_GetItem(args, 0);
1914 if (PyTuple_Check(o)) {
1915 o = SplitObj(o);
1916 return o;
1917 }
1918 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001919 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001920 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001921 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001922}
1923
1924static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001925Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001926{
Barry Warsawfa701a81997-01-16 00:15:11 +00001927 char *s = Merge(args);
1928 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001929
Barry Warsawfa701a81997-01-16 00:15:11 +00001930 if (s) {
1931 res = PyString_FromString(s);
1932 ckfree(s);
1933 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001934
1935 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001936}
1937
Barry Warsawfa701a81997-01-16 00:15:11 +00001938
1939
Guido van Rossum18468821994-06-20 07:49:28 +00001940/** Tcl Command **/
1941
Guido van Rossum00d93061998-05-28 23:06:38 +00001942/* Client data struct */
1943typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001944 PyObject *self;
1945 PyObject *func;
1946} PythonCmd_ClientData;
1947
1948static int
Fred Drake509d79a2000-07-08 04:04:38 +00001949PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001950{
1951 errorInCmd = 1;
1952 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1953 LEAVE_PYTHON
1954 return TCL_ERROR;
1955}
1956
Guido van Rossum18468821994-06-20 07:49:28 +00001957/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001958 * function or method.
1959 */
Guido van Rossum18468821994-06-20 07:49:28 +00001960static int
Fred Drake509d79a2000-07-08 04:04:38 +00001961PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001962{
Guido van Rossum00d93061998-05-28 23:06:38 +00001963 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001964 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001965 int i, rv;
1966 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001967
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001968 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001969
Barry Warsawfa701a81997-01-16 00:15:11 +00001970 /* TBD: no error checking here since we know, via the
1971 * Tkapp_CreateCommand() that the client data is a two-tuple
1972 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001973 self = data->self;
1974 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001975
Barry Warsawfa701a81997-01-16 00:15:11 +00001976 /* Create argument list (argv1, ..., argvN) */
1977 if (!(arg = PyTuple_New(argc - 1)))
1978 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001979
Barry Warsawfa701a81997-01-16 00:15:11 +00001980 for (i = 0; i < (argc - 1); i++) {
1981 PyObject *s = PyString_FromString(argv[i + 1]);
1982 if (!s || PyTuple_SetItem(arg, i, s)) {
1983 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001984 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001985 }
1986 }
1987 res = PyEval_CallObject(func, arg);
1988 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001989
Barry Warsawfa701a81997-01-16 00:15:11 +00001990 if (res == NULL)
1991 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001992
Barry Warsawfa701a81997-01-16 00:15:11 +00001993 if (!(tmp = PyList_New(0))) {
1994 Py_DECREF(res);
1995 return PythonCmd_Error(interp);
1996 }
1997
Guido van Rossum2834b972000-10-06 16:58:26 +00001998 s = AsString(res, tmp);
1999 if (s == NULL) {
2000 rv = PythonCmd_Error(interp);
2001 }
2002 else {
2003 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
2004 rv = TCL_OK;
2005 }
2006
Barry Warsawfa701a81997-01-16 00:15:11 +00002007 Py_DECREF(res);
2008 Py_DECREF(tmp);
2009
Guido van Rossum00d93061998-05-28 23:06:38 +00002010 LEAVE_PYTHON
2011
Guido van Rossum2834b972000-10-06 16:58:26 +00002012 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002013}
2014
2015static void
Fred Drake509d79a2000-07-08 04:04:38 +00002016PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002017{
Guido van Rossum00d93061998-05-28 23:06:38 +00002018 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2019
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002020 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002021 Py_XDECREF(data->self);
2022 Py_XDECREF(data->func);
2023 PyMem_DEL(data);
2024 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002025}
2026
Barry Warsawfa701a81997-01-16 00:15:11 +00002027
2028
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002029
2030TCL_DECLARE_MUTEX(command_mutex)
2031
2032typedef struct CommandEvent{
2033 Tcl_Event ev;
2034 Tcl_Interp* interp;
2035 char *name;
2036 int create;
2037 int *status;
2038 ClientData *data;
2039 Tcl_Condition done;
2040} CommandEvent;
2041
2042static int
2043Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002044{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002045 if (ev->create)
2046 *ev->status = Tcl_CreateCommand(
2047 ev->interp, ev->name, PythonCmd,
2048 ev->data, PythonCmdDelete) == NULL;
2049 else
2050 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2051 Tcl_MutexLock(&command_mutex);
2052 Tcl_ConditionNotify(&ev->done);
2053 Tcl_MutexUnlock(&command_mutex);
2054 return 1;
2055}
2056
2057static PyObject *
2058Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2059{
2060 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002061 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002062 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002063 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002064 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002065
Guido van Rossum43713e52000-02-29 13:59:29 +00002066 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002067 return NULL;
2068 if (!PyCallable_Check(func)) {
2069 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002070 return NULL;
2071 }
Guido van Rossum18468821994-06-20 07:49:28 +00002072
Martin v. Löwisa9656492003-03-30 08:44:58 +00002073#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002074 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002075 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002076 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002077#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002078
Guido van Rossum00d93061998-05-28 23:06:38 +00002079 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002080 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002081 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002082 Py_XINCREF(self);
2083 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002084 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002085 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002086
2087 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2088 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2089 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2090 ev->interp = self->interp;
2091 ev->create = 1;
2092 ev->name = cmdName;
2093 ev->data = (ClientData)data;
2094 ev->status = &err;
2095 ev->done = NULL;
2096 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2097 }
2098 else {
2099 ENTER_TCL
2100 err = Tcl_CreateCommand(
2101 Tkapp_Interp(self), cmdName, PythonCmd,
2102 (ClientData)data, PythonCmdDelete) == NULL;
2103 LEAVE_TCL
2104 }
2105 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002106 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002107 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002108 return NULL;
2109 }
Guido van Rossum18468821994-06-20 07:49:28 +00002110
Barry Warsawfa701a81997-01-16 00:15:11 +00002111 Py_INCREF(Py_None);
2112 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002113}
2114
Barry Warsawfa701a81997-01-16 00:15:11 +00002115
2116
Guido van Rossum18468821994-06-20 07:49:28 +00002117static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002118Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002119{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002120 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002121 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002122 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002123
Guido van Rossum43713e52000-02-29 13:59:29 +00002124 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002125 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002126 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2127 CommandEvent *ev;
2128 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2129 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2130 ev->interp = self->interp;
2131 ev->create = 0;
2132 ev->name = cmdName;
2133 ev->status = &err;
2134 ev->done = NULL;
2135 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2136 &command_mutex);
2137 }
2138 else {
2139 ENTER_TCL
2140 err = Tcl_DeleteCommand(self->interp, cmdName);
2141 LEAVE_TCL
2142 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002143 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002144 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2145 return NULL;
2146 }
2147 Py_INCREF(Py_None);
2148 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002149}
2150
Barry Warsawfa701a81997-01-16 00:15:11 +00002151
2152
Guido van Rossum00d93061998-05-28 23:06:38 +00002153#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002154/** File Handler **/
2155
Guido van Rossum00d93061998-05-28 23:06:38 +00002156typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002157 PyObject *func;
2158 PyObject *file;
2159 int id;
2160 struct _fhcdata *next;
2161} FileHandler_ClientData;
2162
2163static FileHandler_ClientData *HeadFHCD;
2164
2165static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002166NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002167{
2168 FileHandler_ClientData *p;
2169 p = PyMem_NEW(FileHandler_ClientData, 1);
2170 if (p != NULL) {
2171 Py_XINCREF(func);
2172 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002173 p->func = func;
2174 p->file = file;
2175 p->id = id;
2176 p->next = HeadFHCD;
2177 HeadFHCD = p;
2178 }
2179 return p;
2180}
2181
2182static void
Fred Drake509d79a2000-07-08 04:04:38 +00002183DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002184{
2185 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002186
2187 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002188 while ((p = *pp) != NULL) {
2189 if (p->id == id) {
2190 *pp = p->next;
2191 Py_XDECREF(p->func);
2192 Py_XDECREF(p->file);
2193 PyMem_DEL(p);
2194 }
2195 else
2196 pp = &p->next;
2197 }
2198}
2199
Guido van Rossuma597dde1995-01-10 20:56:29 +00002200static void
Fred Drake509d79a2000-07-08 04:04:38 +00002201FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002202{
Guido van Rossum00d93061998-05-28 23:06:38 +00002203 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002204 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002205
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002206 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002207 func = data->func;
2208 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002209
Barry Warsawfa701a81997-01-16 00:15:11 +00002210 arg = Py_BuildValue("(Oi)", file, (long) mask);
2211 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002212 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002213
2214 if (res == NULL) {
2215 errorInCmd = 1;
2216 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2217 }
2218 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002219 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002220}
2221
Guido van Rossum18468821994-06-20 07:49:28 +00002222static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002223Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2224 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002225{
Guido van Rossum00d93061998-05-28 23:06:38 +00002226 FileHandler_ClientData *data;
2227 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002228 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002229
Guido van Rossum2834b972000-10-06 16:58:26 +00002230 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2231 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002232 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002233
Martin v. Löwisa9656492003-03-30 08:44:58 +00002234#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002235 if (!self && !tcl_lock) {
2236 /* We don't have the Tcl lock since Tcl is threaded. */
2237 PyErr_SetString(PyExc_RuntimeError,
2238 "_tkinter.createfilehandler not supported "
2239 "for threaded Tcl");
2240 return NULL;
2241 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002242#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002243
2244 if (self) {
2245 CHECK_TCL_APPARTMENT;
2246 }
2247
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002248 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002249 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002250 return NULL;
2251 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002252 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002253 return NULL;
2254 }
2255
Guido van Rossuma80649b2000-03-28 20:07:05 +00002256 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002257 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002258 return NULL;
2259
Barry Warsawfa701a81997-01-16 00:15:11 +00002260 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002261 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002262 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002263 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002264 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002265 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002266}
2267
2268static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002269Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002270{
Barry Warsawfa701a81997-01-16 00:15:11 +00002271 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002272 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002273
Guido van Rossum43713e52000-02-29 13:59:29 +00002274 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002275 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002276
Martin v. Löwisa9656492003-03-30 08:44:58 +00002277#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002278 if (!self && !tcl_lock) {
2279 /* We don't have the Tcl lock since Tcl is threaded. */
2280 PyErr_SetString(PyExc_RuntimeError,
2281 "_tkinter.deletefilehandler not supported "
2282 "for threaded Tcl");
2283 return NULL;
2284 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002285#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002286
2287 if (self) {
2288 CHECK_TCL_APPARTMENT;
2289 }
2290
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002291 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002292 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002293 return NULL;
2294
Guido van Rossuma80649b2000-03-28 20:07:05 +00002295 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002296
Barry Warsawfa701a81997-01-16 00:15:11 +00002297 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002298 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002299 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002300 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002301 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002302 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002303}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002304#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002305
Barry Warsawfa701a81997-01-16 00:15:11 +00002306
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002307/**** Tktt Object (timer token) ****/
2308
Jeremy Hylton938ace62002-07-17 16:30:39 +00002309static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002310
Guido van Rossum00d93061998-05-28 23:06:38 +00002311typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002312 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002313 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002314 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002315} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002316
2317static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002318Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002319{
Barry Warsawfa701a81997-01-16 00:15:11 +00002320 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002321 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002322
Guido van Rossum43713e52000-02-29 13:59:29 +00002323 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002324 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002325 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002326 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002327 v->token = NULL;
2328 }
2329 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002330 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002331 Py_DECREF(func);
2332 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002333 }
2334 Py_INCREF(Py_None);
2335 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002336}
2337
2338static PyMethodDef Tktt_methods[] =
2339{
Neal Norwitzb0493252002-03-31 14:44:22 +00002340 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002341 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002342};
2343
2344static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002345Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002346{
Barry Warsawfa701a81997-01-16 00:15:11 +00002347 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002348
Guido van Rossumb18618d2000-05-03 23:44:39 +00002349 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002350 if (v == NULL)
2351 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002352
Guido van Rossum00d93061998-05-28 23:06:38 +00002353 Py_INCREF(func);
2354 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002355 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002356
2357 /* Extra reference, deleted when called or when handler is deleted */
2358 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002359 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002360}
2361
2362static void
Fred Drake509d79a2000-07-08 04:04:38 +00002363Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002364{
Guido van Rossum00d93061998-05-28 23:06:38 +00002365 TkttObject *v = (TkttObject *)self;
2366 PyObject *func = v->func;
2367
2368 Py_XDECREF(func);
2369
Guido van Rossumb18618d2000-05-03 23:44:39 +00002370 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002371}
2372
Guido van Rossum597ac201998-05-12 14:36:19 +00002373static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002374Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002375{
Barry Warsawfa701a81997-01-16 00:15:11 +00002376 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002377 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002378
Tim Peters885d4572001-11-28 20:27:42 +00002379 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002380 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002381 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002382}
2383
2384static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002385Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002386{
Barry Warsawfa701a81997-01-16 00:15:11 +00002387 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002388}
2389
2390static PyTypeObject Tktt_Type =
2391{
Guido van Rossum35d43371997-08-02 00:09:09 +00002392 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002393 0, /*ob_size */
2394 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002395 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002396 0, /*tp_itemsize */
2397 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002398 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002399 Tktt_GetAttr, /*tp_getattr */
2400 0, /*tp_setattr */
2401 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002402 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002403 0, /*tp_as_number */
2404 0, /*tp_as_sequence */
2405 0, /*tp_as_mapping */
2406 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002407};
2408
Barry Warsawfa701a81997-01-16 00:15:11 +00002409
2410
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002411/** Timer Handler **/
2412
2413static void
Fred Drake509d79a2000-07-08 04:04:38 +00002414TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002415{
Guido van Rossum00d93061998-05-28 23:06:38 +00002416 TkttObject *v = (TkttObject *)clientData;
2417 PyObject *func = v->func;
2418 PyObject *res;
2419
2420 if (func == NULL)
2421 return;
2422
2423 v->func = NULL;
2424
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002425 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002426
2427 res = PyEval_CallObject(func, NULL);
2428 Py_DECREF(func);
2429 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002430
Barry Warsawfa701a81997-01-16 00:15:11 +00002431 if (res == NULL) {
2432 errorInCmd = 1;
2433 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2434 }
2435 else
2436 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002437
2438 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002439}
2440
2441static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002442Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002443{
Barry Warsawfa701a81997-01-16 00:15:11 +00002444 int milliseconds;
2445 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002446 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002447
Guido van Rossum2834b972000-10-06 16:58:26 +00002448 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2449 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002450 return NULL;
2451 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002452 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002453 return NULL;
2454 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002455
Martin v. Löwisa9656492003-03-30 08:44:58 +00002456#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002457 if (!self && !tcl_lock) {
2458 /* We don't have the Tcl lock since Tcl is threaded. */
2459 PyErr_SetString(PyExc_RuntimeError,
2460 "_tkinter.createtimerhandler not supported "
2461 "for threaded Tcl");
2462 return NULL;
2463 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002464#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002465
2466 if (self) {
2467 CHECK_TCL_APPARTMENT;
2468 }
2469
Guido van Rossum00d93061998-05-28 23:06:38 +00002470 v = Tktt_New(func);
2471 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2472 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002473
Guido van Rossum00d93061998-05-28 23:06:38 +00002474 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002475}
2476
Barry Warsawfa701a81997-01-16 00:15:11 +00002477
Guido van Rossum18468821994-06-20 07:49:28 +00002478/** Event Loop **/
2479
Guido van Rossum18468821994-06-20 07:49:28 +00002480static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002481Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002482{
Barry Warsawfa701a81997-01-16 00:15:11 +00002483 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002484 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002485#ifdef WITH_THREAD
2486 PyThreadState *tstate = PyThreadState_Get();
2487#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002488
Guido van Rossum43713e52000-02-29 13:59:29 +00002489 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002490 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002491
Martin v. Löwisa9656492003-03-30 08:44:58 +00002492#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002493 if (!self && !tcl_lock) {
2494 /* We don't have the Tcl lock since Tcl is threaded. */
2495 PyErr_SetString(PyExc_RuntimeError,
2496 "_tkinter.mainloop not supported "
2497 "for threaded Tcl");
2498 return NULL;
2499 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002500#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002501
2502 if (self) {
2503 CHECK_TCL_APPARTMENT;
2504 self->dispatching = 1;
2505 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002506
Barry Warsawfa701a81997-01-16 00:15:11 +00002507 quitMainLoop = 0;
2508 while (Tk_GetNumMainWindows() > threshold &&
2509 !quitMainLoop &&
2510 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002511 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002512 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002513
2514#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002515 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002516 /* Allow other Python threads to run. */
2517 ENTER_TCL
2518 result = Tcl_DoOneEvent(0);
2519 LEAVE_TCL
2520 }
2521 else {
2522 Py_BEGIN_ALLOW_THREADS
2523 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2524 tcl_tstate = tstate;
2525 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2526 tcl_tstate = NULL;
2527 if(tcl_lock)PyThread_release_lock(tcl_lock);
2528 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002529 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002530 Py_END_ALLOW_THREADS
2531 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002532#else
2533 result = Tcl_DoOneEvent(0);
2534#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002535
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002536 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002537 if (self)
2538 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002539 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002540 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002541 if (result < 0)
2542 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002543 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002544 if (self)
2545 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002546 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002547
Barry Warsawfa701a81997-01-16 00:15:11 +00002548 if (errorInCmd) {
2549 errorInCmd = 0;
2550 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2551 excInCmd = valInCmd = trbInCmd = NULL;
2552 return NULL;
2553 }
2554 Py_INCREF(Py_None);
2555 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002556}
2557
2558static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002559Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002560{
Guido van Rossum35d43371997-08-02 00:09:09 +00002561 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002562 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002563
Guido van Rossum43713e52000-02-29 13:59:29 +00002564 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002565 return NULL;
2566
Guido van Rossum00d93061998-05-28 23:06:38 +00002567 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002568 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002569 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002570 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002571}
2572
2573static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002574Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002575{
2576
Guido van Rossum43713e52000-02-29 13:59:29 +00002577 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002578 return NULL;
2579
2580 quitMainLoop = 1;
2581 Py_INCREF(Py_None);
2582 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002583}
2584
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002585static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002586Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002587{
2588
Guido van Rossum43713e52000-02-29 13:59:29 +00002589 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002590 return NULL;
2591
2592 return PyInt_FromLong((long)Tkapp_Interp(self));
2593}
2594
Barry Warsawfa701a81997-01-16 00:15:11 +00002595
Martin v. Löwisffad6332002-11-26 09:28:05 +00002596static PyObject *
2597Tkapp_WantObjects(PyObject *self, PyObject *args)
2598{
2599
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002600 int wantobjects;
2601 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002602 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002603 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002604
2605 Py_INCREF(Py_None);
2606 return Py_None;
2607}
2608
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002609static PyObject *
2610Tkapp_WillDispatch(PyObject *self, PyObject *args)
2611{
2612
2613 ((TkappObject*)self)->dispatching = 1;
2614
2615 Py_INCREF(Py_None);
2616 return Py_None;
2617}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002618
Barry Warsawfa701a81997-01-16 00:15:11 +00002619
Guido van Rossum18468821994-06-20 07:49:28 +00002620/**** Tkapp Method List ****/
2621
2622static PyMethodDef Tkapp_methods[] =
2623{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002624 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002625 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002626 {"call", Tkapp_Call, METH_OLDARGS},
2627 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2628 {"eval", Tkapp_Eval, METH_VARARGS},
2629 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2630 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2631 {"record", Tkapp_Record, METH_VARARGS},
2632 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2633 {"setvar", Tkapp_SetVar, METH_VARARGS},
2634 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2635 {"getvar", Tkapp_GetVar, METH_VARARGS},
2636 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2637 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2638 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2639 {"getint", Tkapp_GetInt, METH_VARARGS},
2640 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2641 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2642 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2643 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2644 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2645 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2646 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2647 {"split", Tkapp_Split, METH_VARARGS},
2648 {"merge", Tkapp_Merge, METH_OLDARGS},
2649 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2650 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002651#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002652 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2653 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002654#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002655 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2656 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2657 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2658 {"quit", Tkapp_Quit, METH_VARARGS},
2659 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002660 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002661};
2662
Barry Warsawfa701a81997-01-16 00:15:11 +00002663
2664
Guido van Rossum18468821994-06-20 07:49:28 +00002665/**** Tkapp Type Methods ****/
2666
2667static void
Fred Drake509d79a2000-07-08 04:04:38 +00002668Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002669{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002670 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002671 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002672 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002673 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002674 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002675 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002676}
2677
2678static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002679Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002680{
Guido van Rossum35d43371997-08-02 00:09:09 +00002681 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002682}
2683
2684static PyTypeObject Tkapp_Type =
2685{
Guido van Rossum35d43371997-08-02 00:09:09 +00002686 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002687 0, /*ob_size */
2688 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002689 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002690 0, /*tp_itemsize */
2691 Tkapp_Dealloc, /*tp_dealloc */
2692 0, /*tp_print */
2693 Tkapp_GetAttr, /*tp_getattr */
2694 0, /*tp_setattr */
2695 0, /*tp_compare */
2696 0, /*tp_repr */
2697 0, /*tp_as_number */
2698 0, /*tp_as_sequence */
2699 0, /*tp_as_mapping */
2700 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002701};
2702
Barry Warsawfa701a81997-01-16 00:15:11 +00002703
2704
Guido van Rossum18468821994-06-20 07:49:28 +00002705/**** Tkinter Module ****/
2706
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002707typedef struct {
2708 PyObject* tuple;
2709 int size; /* current size */
2710 int maxsize; /* allocated size */
2711} FlattenContext;
2712
2713static int
2714_bump(FlattenContext* context, int size)
2715{
Guido van Rossum2834b972000-10-06 16:58:26 +00002716 /* expand tuple to hold (at least) size new items.
2717 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002718
2719 int maxsize = context->maxsize * 2;
2720
2721 if (maxsize < context->size + size)
2722 maxsize = context->size + size;
2723
2724 context->maxsize = maxsize;
2725
Tim Peters4324aa32001-05-28 22:30:08 +00002726 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002727}
2728
2729static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002730_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002731{
2732 /* add tuple or list to argument tuple (recursively) */
2733
2734 int i, size;
2735
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002736 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002737 PyErr_SetString(PyExc_ValueError,
2738 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002739 return 0;
2740 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002741 size = PyList_GET_SIZE(item);
2742 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002743 if (context->size + size > context->maxsize &&
2744 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002745 return 0;
2746 /* copy items to output tuple */
2747 for (i = 0; i < size; i++) {
2748 PyObject *o = PyList_GET_ITEM(item, i);
2749 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002750 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002751 return 0;
2752 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002753 if (context->size + 1 > context->maxsize &&
2754 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002755 return 0;
2756 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002757 PyTuple_SET_ITEM(context->tuple,
2758 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002759 }
2760 }
2761 } else if (PyTuple_Check(item)) {
2762 /* same, for tuples */
2763 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002764 if (context->size + size > context->maxsize &&
2765 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002766 return 0;
2767 for (i = 0; i < size; i++) {
2768 PyObject *o = PyTuple_GET_ITEM(item, i);
2769 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002770 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002771 return 0;
2772 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002773 if (context->size + 1 > context->maxsize &&
2774 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002775 return 0;
2776 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002777 PyTuple_SET_ITEM(context->tuple,
2778 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002779 }
2780 }
2781 } else {
2782 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2783 return 0;
2784 }
2785 return 1;
2786}
2787
2788static PyObject *
2789Tkinter_Flatten(PyObject* self, PyObject* args)
2790{
2791 FlattenContext context;
2792 PyObject* item;
2793
2794 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2795 return NULL;
2796
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002797 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002798 if (context.maxsize <= 0)
2799 return PyTuple_New(0);
2800
2801 context.tuple = PyTuple_New(context.maxsize);
2802 if (!context.tuple)
2803 return NULL;
2804
2805 context.size = 0;
2806
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002807 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002808 return NULL;
2809
Tim Peters4324aa32001-05-28 22:30:08 +00002810 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002811 return NULL;
2812
2813 return context.tuple;
2814}
2815
Guido van Rossum18468821994-06-20 07:49:28 +00002816static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002817Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002818{
Barry Warsawfa701a81997-01-16 00:15:11 +00002819 char *screenName = NULL;
2820 char *baseName = NULL;
2821 char *className = NULL;
2822 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002823 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002824
Guido van Rossum35d43371997-08-02 00:09:09 +00002825 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002826 if (baseName != NULL)
2827 baseName++;
2828 else
2829 baseName = Py_GetProgramName();
2830 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002831
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002832 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002833 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002834 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002835 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002836
Barry Warsawfa701a81997-01-16 00:15:11 +00002837 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002838 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002839}
2840
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002841static PyObject *
2842Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2843{
2844 int new_val;
2845 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2846 return NULL;
2847 if (new_val < 0) {
2848 PyErr_SetString(PyExc_ValueError,
2849 "busywaitinterval must be >= 0");
2850 return NULL;
2851 }
2852 Tkinter_busywaitinterval = new_val;
2853 Py_INCREF(Py_None);
2854 return Py_None;
2855}
2856
2857static char setbusywaitinterval_doc[] =
2858"setbusywaitinterval(n) -> None\n\
2859\n\
2860Set the busy-wait interval in milliseconds between successive\n\
2861calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2862It should be set to a divisor of the maximum time between\n\
2863frames in an animation.";
2864
2865static PyObject *
2866Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2867{
2868 return PyInt_FromLong(Tkinter_busywaitinterval);
2869}
2870
2871static char getbusywaitinterval_doc[] =
2872"getbusywaitinterval() -> int\n\
2873\n\
2874Return the current busy-wait interval between successive\n\
2875calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2876
Guido van Rossum18468821994-06-20 07:49:28 +00002877static PyMethodDef moduleMethods[] =
2878{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002879 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2880 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002881#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002882 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2883 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002884#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002885 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2886 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2887 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2888 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002889 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2890 setbusywaitinterval_doc},
2891 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2892 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002893 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002894};
2895
Guido van Rossum7bf15641998-05-22 18:28:17 +00002896#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002897
2898static int stdin_ready = 0;
2899
Guido van Rossumad4db171998-06-13 13:56:28 +00002900#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002901static void
Fred Drake509d79a2000-07-08 04:04:38 +00002902MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002903{
2904 stdin_ready = 1;
2905}
Guido van Rossumad4db171998-06-13 13:56:28 +00002906#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002907
Martin v. Löwisa9656492003-03-30 08:44:58 +00002908#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002909static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002910#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002911
Guido van Rossum18468821994-06-20 07:49:28 +00002912static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002913EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002914{
Guido van Rossumad4db171998-06-13 13:56:28 +00002915#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002916 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002917#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002918#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002919 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002920#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002921 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002922 errorInCmd = 0;
2923#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002924 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002925 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002926#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002927 while (!errorInCmd && !stdin_ready) {
2928 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002929#ifdef MS_WINDOWS
2930 if (_kbhit()) {
2931 stdin_ready = 1;
2932 break;
2933 }
2934#endif
2935#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002936 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002937 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002938 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002939
Guido van Rossum00d93061998-05-28 23:06:38 +00002940 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002941
2942 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002943 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002944 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002945 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002946 Py_END_ALLOW_THREADS
2947#else
2948 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002949#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002950
2951 if (result < 0)
2952 break;
2953 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002954#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002955 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002956#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002957 if (errorInCmd) {
2958 errorInCmd = 0;
2959 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2960 excInCmd = valInCmd = trbInCmd = NULL;
2961 PyErr_Print();
2962 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002963#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002964 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002965#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002966 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002967}
Guido van Rossum18468821994-06-20 07:49:28 +00002968
Guido van Rossum00d93061998-05-28 23:06:38 +00002969#endif
2970
Guido van Rossum7bf15641998-05-22 18:28:17 +00002971static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002972EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002973{
Guido van Rossum00d93061998-05-28 23:06:38 +00002974#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002975 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002976#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002977 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002978#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002979 PyOS_InputHook = EventHook;
2980 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002981#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002982}
2983
2984static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002985DisableEventHook(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 (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2989 PyOS_InputHook = NULL;
2990 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002991#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002992}
2993
Barry Warsawfa701a81997-01-16 00:15:11 +00002994
2995/* all errors will be checked in one fell swoop in init_tkinter() */
2996static void
Fred Drake509d79a2000-07-08 04:04:38 +00002997ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002998{
2999 PyObject *v = PyInt_FromLong(val);
3000 if (v) {
3001 PyDict_SetItemString(d, name, v);
3002 Py_DECREF(v);
3003 }
3004}
3005static void
Fred Drake509d79a2000-07-08 04:04:38 +00003006ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003007{
3008 PyObject *v = PyString_FromString(val);
3009 if (v) {
3010 PyDict_SetItemString(d, name, v);
3011 Py_DECREF(v);
3012 }
3013}
3014
3015
Mark Hammond62b1ab12002-07-23 06:31:15 +00003016PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003017init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003018{
Barry Warsawfa701a81997-01-16 00:15:11 +00003019 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003020
Barry Warsawfa701a81997-01-16 00:15:11 +00003021 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003022
3023#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003024 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003025#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003026
Barry Warsawfa701a81997-01-16 00:15:11 +00003027 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00003028
Barry Warsawfa701a81997-01-16 00:15:11 +00003029 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003030 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003031 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003032
Guido van Rossum35d43371997-08-02 00:09:09 +00003033 ins_long(d, "READABLE", TCL_READABLE);
3034 ins_long(d, "WRITABLE", TCL_WRITABLE);
3035 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3036 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3037 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3038 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3039 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3040 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3041 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003042 ins_string(d, "TK_VERSION", TK_VERSION);
3043 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003044
Guido van Rossum83551bf1997-09-13 00:44:23 +00003045 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003046
3047 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003048 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3049
Martin v. Löwisffad6332002-11-26 09:28:05 +00003050 PyTclObject_Type.ob_type = &PyType_Type;
3051 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003052
3053#ifdef TK_AQUA
3054 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3055 * start waking up. Note that Tcl_FindExecutable will do this, this
3056 * code must be above it! The original warning from
3057 * tkMacOSXAppInit.c is copied below.
3058 *
3059 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3060 * Tcl interpreter for now. It probably should work to do this
3061 * in the other order, but for now it doesn't seem to.
3062 *
3063 */
3064 Tk_MacOSXSetupTkNotifier();
3065#endif
3066
3067
Guido van Rossume187b0e2000-03-27 21:46:29 +00003068 /* This helps the dynamic loader; in Unicode aware Tcl versions
3069 it also helps Tcl find its encodings. */
3070 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003071
Barry Warsawfa701a81997-01-16 00:15:11 +00003072 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003073 return;
3074
Guido van Rossum43ff8681998-07-14 18:02:13 +00003075#if 0
3076 /* This was not a good idea; through <Destroy> bindings,
3077 Tcl_Finalize() may invoke Python code but at that point the
3078 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003079 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003080#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003081
Jack Jansen34cc5c31995-10-31 16:15:12 +00003082#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003083 /*
3084 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
3085 ** Most of the initializations in that routine (toolbox init calls and
3086 ** such) have already been done for us, so we only need these.
3087 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003088 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003089
3090 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00003091#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00003092 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00003093#endif /* GENERATINGCFM */
3094#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00003095}
Guido van Rossum9722ad81995-09-22 23:49:28 +00003096
Guido van Rossumec22c921996-02-25 04:50:29 +00003097
Barry Warsawfa701a81997-01-16 00:15:11 +00003098
Guido van Rossum9722ad81995-09-22 23:49:28 +00003099#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003100
3101/*
Guido van Rossumec22c921996-02-25 04:50:29 +00003102** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003103*/
3104
Guido van Rossum9722ad81995-09-22 23:49:28 +00003105void
3106panic(char * format, ...)
3107{
Barry Warsawfa701a81997-01-16 00:15:11 +00003108 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003109
Barry Warsawfa701a81997-01-16 00:15:11 +00003110 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003111
Guido van Rossum227cf761998-08-05 13:53:32 +00003112 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00003113 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003114
Barry Warsawfa701a81997-01-16 00:15:11 +00003115 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003116
Barry Warsawfa701a81997-01-16 00:15:11 +00003117 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00003118}
Jack Jansen40b546d1995-11-14 10:34:45 +00003119
Guido van Rossumec22c921996-02-25 04:50:29 +00003120/*
3121** Pass events to SIOUX before passing them to Tk.
3122*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003123
Guido van Rossumec22c921996-02-25 04:50:29 +00003124static int
Fred Drake509d79a2000-07-08 04:04:38 +00003125PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003126{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003127 WindowPtr frontwin;
3128 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00003129 ** Sioux eats too many events, so we don't pass it everything. We
3130 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003131 ** the Sioux window is frontmost. This means that Tk menus don't work
3132 ** in that case, but at least we can scroll the sioux window.
3133 ** Note that the SIOUXIsAppWindow() routine we use here is not really
3134 ** part of the external interface of Sioux...
3135 */
3136 frontwin = FrontWindow();
3137 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
3138 if (SIOUXHandleOneEvent(eventPtr))
3139 return 0; /* Nothing happened to the Tcl event queue */
3140 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003141 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003142}
3143
Guido van Rossumec22c921996-02-25 04:50:29 +00003144#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003145
3146/*
3147** Additional Mac specific code for dealing with shared libraries.
3148*/
3149
3150#include <Resources.h>
3151#include <CodeFragments.h>
3152
3153static int loaded_from_shlib = 0;
3154static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003155
Jack Jansen34cc5c31995-10-31 16:15:12 +00003156/*
3157** If this module is dynamically loaded the following routine should
3158** be the init routine. It takes care of adding the shared library to
3159** the resource-file chain, so that the tk routines can find their
3160** resources.
3161*/
3162OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003163init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003164{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00003165 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00003166 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003167 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003168 library_fss = *data->fragLocator.u.onDisk.fileSpec;
3169 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003170 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003171 library_fss = *data->fragLocator.u.inSegs.fileSpec;
3172 loaded_from_shlib = 1;
3173 }
3174 return noErr;
3175}
3176
3177/*
3178** Insert the library resources into the search path. Put them after
3179** the resources from the application. Again, we ignore errors.
3180*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003181static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003182mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003183{
3184 if ( !loaded_from_shlib )
3185 return;
3186 (void)FSpOpenResFile(&library_fss, fsRdPerm);
3187}
3188
Guido van Rossumec22c921996-02-25 04:50:29 +00003189#endif /* GENERATINGCFM */
3190#endif /* macintosh */