blob: 288ed153e97573d1ae51acfc32b83df27da745b6 [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
1650 res = FromObj(self, tres);
1651 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001652 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001653}
1654
1655static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001656Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001657{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001658 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001659}
1660
1661static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001662Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001663{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001664 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001665}
1666
Barry Warsawfa701a81997-01-16 00:15:11 +00001667
1668
Guido van Rossum18468821994-06-20 07:49:28 +00001669static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001670UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001671{
Guido van Rossum35d43371997-08-02 00:09:09 +00001672 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001673 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001674 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001675
Guido van Rossum43713e52000-02-29 13:59:29 +00001676 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001677 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001678
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001679 ENTER_TCL
1680 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1681 ENTER_OVERLAP
1682 if (code == TCL_ERROR)
1683 res = Tkinter_Error(self);
1684 else {
1685 Py_INCREF(Py_None);
1686 res = Py_None;
1687 }
1688 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001689 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001690}
1691
1692static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001693Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001694{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001695 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001696}
1697
1698static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001699Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001700{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001701 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001702}
1703
Barry Warsawfa701a81997-01-16 00:15:11 +00001704
1705
Guido van Rossum18468821994-06-20 07:49:28 +00001706/** Tcl to Python **/
1707
1708static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001709Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001710{
Barry Warsawfa701a81997-01-16 00:15:11 +00001711 char *s;
1712 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001713
Martin v. Löwisffad6332002-11-26 09:28:05 +00001714 if (PyTuple_Size(args) == 1) {
1715 PyObject* o = PyTuple_GetItem(args, 0);
1716 if (PyInt_Check(o)) {
1717 Py_INCREF(o);
1718 return o;
1719 }
1720 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001721 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001722 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001723 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001724 return Tkinter_Error(self);
1725 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001726}
1727
1728static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001729Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001730{
Barry Warsawfa701a81997-01-16 00:15:11 +00001731 char *s;
1732 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001733
Martin v. Löwisffad6332002-11-26 09:28:05 +00001734 if (PyTuple_Size(args) == 1) {
1735 PyObject *o = PyTuple_GetItem(args, 0);
1736 if (PyFloat_Check(o)) {
1737 Py_INCREF(o);
1738 return o;
1739 }
1740 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001741 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001742 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001743 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001744 return Tkinter_Error(self);
1745 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001746}
1747
1748static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001749Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001750{
Barry Warsawfa701a81997-01-16 00:15:11 +00001751 char *s;
1752 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001753
Martin v. Löwisffad6332002-11-26 09:28:05 +00001754 if (PyTuple_Size(args) == 1) {
1755 PyObject *o = PyTuple_GetItem(args, 0);
1756 if (PyInt_Check(o)) {
1757 Py_INCREF(o);
1758 return o;
1759 }
1760 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001761 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001762 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001763 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1764 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001765 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001766}
1767
1768static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001769Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001770{
Barry Warsawfa701a81997-01-16 00:15:11 +00001771 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001772 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001773 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001774
Guido van Rossum43713e52000-02-29 13:59:29 +00001775 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001776 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001777
1778 CHECK_TCL_APPARTMENT;
1779
Guido van Rossum00d93061998-05-28 23:06:38 +00001780 ENTER_TCL
1781 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001782 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001783 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001784 res = Tkinter_Error(self);
1785 else
1786 res = Py_BuildValue("s", Tkapp_Result(self));
1787 LEAVE_OVERLAP_TCL
1788 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001789}
1790
1791static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001792Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001793{
Barry Warsawfa701a81997-01-16 00:15:11 +00001794 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001795 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001796 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001797 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001798
Guido van Rossum43713e52000-02-29 13:59:29 +00001799 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001800 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001801
1802 CHECK_TCL_APPARTMENT;
1803
Guido van Rossum00d93061998-05-28 23:06:38 +00001804 ENTER_TCL
1805 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001806 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001807 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001808 res = Tkinter_Error(self);
1809 else
1810 res = Py_BuildValue("l", v);
1811 LEAVE_OVERLAP_TCL
1812 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001813}
1814
1815static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001816Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001817{
Barry Warsawfa701a81997-01-16 00:15:11 +00001818 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001819 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001820 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001821 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001822
Guido van Rossum43713e52000-02-29 13:59:29 +00001823 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001824 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001825 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001826 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001827 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001828 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001829 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001830 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001831 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001832 res = Tkinter_Error(self);
1833 else
1834 res = Py_BuildValue("d", v);
1835 LEAVE_OVERLAP_TCL
1836 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001837}
1838
1839static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001840Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001841{
Barry Warsawfa701a81997-01-16 00:15:11 +00001842 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001843 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001844 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001845 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001846
Guido van Rossum43713e52000-02-29 13:59:29 +00001847 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001848 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001849 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001850 ENTER_TCL
1851 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001852 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001853 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001854 res = Tkinter_Error(self);
1855 else
1856 res = Py_BuildValue("i", v);
1857 LEAVE_OVERLAP_TCL
1858 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001859}
1860
Barry Warsawfa701a81997-01-16 00:15:11 +00001861
1862
Guido van Rossum18468821994-06-20 07:49:28 +00001863static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001864Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001865{
Barry Warsawfa701a81997-01-16 00:15:11 +00001866 char *list;
1867 int argc;
1868 char **argv;
1869 PyObject *v;
1870 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001871
Martin v. Löwisffad6332002-11-26 09:28:05 +00001872 if (PyTuple_Size(args) == 1) {
1873 v = PyTuple_GetItem(args, 0);
1874 if (PyTuple_Check(v)) {
1875 Py_INCREF(v);
1876 return v;
1877 }
1878 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001879 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001880 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001881
Barry Warsawfa701a81997-01-16 00:15:11 +00001882 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1883 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001884
Barry Warsawfa701a81997-01-16 00:15:11 +00001885 if (!(v = PyTuple_New(argc)))
1886 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001887
Barry Warsawfa701a81997-01-16 00:15:11 +00001888 for (i = 0; i < argc; i++) {
1889 PyObject *s = PyString_FromString(argv[i]);
1890 if (!s || PyTuple_SetItem(v, i, s)) {
1891 Py_DECREF(v);
1892 v = NULL;
1893 goto finally;
1894 }
1895 }
Guido van Rossum18468821994-06-20 07:49:28 +00001896
Barry Warsawfa701a81997-01-16 00:15:11 +00001897 finally:
1898 ckfree(FREECAST argv);
1899 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001900}
1901
1902static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001903Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001904{
Barry Warsawfa701a81997-01-16 00:15:11 +00001905 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001906
Martin v. Löwisffad6332002-11-26 09:28:05 +00001907 if (PyTuple_Size(args) == 1) {
1908 PyObject* o = PyTuple_GetItem(args, 0);
1909 if (PyTuple_Check(o)) {
1910 o = SplitObj(o);
1911 return o;
1912 }
1913 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001914 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001915 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001916 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001917}
1918
1919static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001920Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001921{
Barry Warsawfa701a81997-01-16 00:15:11 +00001922 char *s = Merge(args);
1923 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001924
Barry Warsawfa701a81997-01-16 00:15:11 +00001925 if (s) {
1926 res = PyString_FromString(s);
1927 ckfree(s);
1928 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001929
1930 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001931}
1932
Barry Warsawfa701a81997-01-16 00:15:11 +00001933
1934
Guido van Rossum18468821994-06-20 07:49:28 +00001935/** Tcl Command **/
1936
Guido van Rossum00d93061998-05-28 23:06:38 +00001937/* Client data struct */
1938typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001939 PyObject *self;
1940 PyObject *func;
1941} PythonCmd_ClientData;
1942
1943static int
Fred Drake509d79a2000-07-08 04:04:38 +00001944PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001945{
1946 errorInCmd = 1;
1947 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1948 LEAVE_PYTHON
1949 return TCL_ERROR;
1950}
1951
Guido van Rossum18468821994-06-20 07:49:28 +00001952/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001953 * function or method.
1954 */
Guido van Rossum18468821994-06-20 07:49:28 +00001955static int
Fred Drake509d79a2000-07-08 04:04:38 +00001956PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001957{
Guido van Rossum00d93061998-05-28 23:06:38 +00001958 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001959 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001960 int i, rv;
1961 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001962
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001963 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001964
Barry Warsawfa701a81997-01-16 00:15:11 +00001965 /* TBD: no error checking here since we know, via the
1966 * Tkapp_CreateCommand() that the client data is a two-tuple
1967 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001968 self = data->self;
1969 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001970
Barry Warsawfa701a81997-01-16 00:15:11 +00001971 /* Create argument list (argv1, ..., argvN) */
1972 if (!(arg = PyTuple_New(argc - 1)))
1973 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001974
Barry Warsawfa701a81997-01-16 00:15:11 +00001975 for (i = 0; i < (argc - 1); i++) {
1976 PyObject *s = PyString_FromString(argv[i + 1]);
1977 if (!s || PyTuple_SetItem(arg, i, s)) {
1978 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001979 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001980 }
1981 }
1982 res = PyEval_CallObject(func, arg);
1983 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001984
Barry Warsawfa701a81997-01-16 00:15:11 +00001985 if (res == NULL)
1986 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001987
Barry Warsawfa701a81997-01-16 00:15:11 +00001988 if (!(tmp = PyList_New(0))) {
1989 Py_DECREF(res);
1990 return PythonCmd_Error(interp);
1991 }
1992
Guido van Rossum2834b972000-10-06 16:58:26 +00001993 s = AsString(res, tmp);
1994 if (s == NULL) {
1995 rv = PythonCmd_Error(interp);
1996 }
1997 else {
1998 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1999 rv = TCL_OK;
2000 }
2001
Barry Warsawfa701a81997-01-16 00:15:11 +00002002 Py_DECREF(res);
2003 Py_DECREF(tmp);
2004
Guido van Rossum00d93061998-05-28 23:06:38 +00002005 LEAVE_PYTHON
2006
Guido van Rossum2834b972000-10-06 16:58:26 +00002007 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002008}
2009
2010static void
Fred Drake509d79a2000-07-08 04:04:38 +00002011PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002012{
Guido van Rossum00d93061998-05-28 23:06:38 +00002013 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2014
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002015 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002016 Py_XDECREF(data->self);
2017 Py_XDECREF(data->func);
2018 PyMem_DEL(data);
2019 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002020}
2021
Barry Warsawfa701a81997-01-16 00:15:11 +00002022
2023
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002024
2025TCL_DECLARE_MUTEX(command_mutex)
2026
2027typedef struct CommandEvent{
2028 Tcl_Event ev;
2029 Tcl_Interp* interp;
2030 char *name;
2031 int create;
2032 int *status;
2033 ClientData *data;
2034 Tcl_Condition done;
2035} CommandEvent;
2036
2037static int
2038Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002039{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002040 if (ev->create)
2041 *ev->status = Tcl_CreateCommand(
2042 ev->interp, ev->name, PythonCmd,
2043 ev->data, PythonCmdDelete) == NULL;
2044 else
2045 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2046 Tcl_MutexLock(&command_mutex);
2047 Tcl_ConditionNotify(&ev->done);
2048 Tcl_MutexUnlock(&command_mutex);
2049 return 1;
2050}
2051
2052static PyObject *
2053Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2054{
2055 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002056 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002057 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002058 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002059 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002060
Guido van Rossum43713e52000-02-29 13:59:29 +00002061 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002062 return NULL;
2063 if (!PyCallable_Check(func)) {
2064 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002065 return NULL;
2066 }
Guido van Rossum18468821994-06-20 07:49:28 +00002067
Martin v. Löwisa9656492003-03-30 08:44:58 +00002068#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002069 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002070 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002071 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002072#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002073
Guido van Rossum00d93061998-05-28 23:06:38 +00002074 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002075 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002076 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002077 Py_XINCREF(self);
2078 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002079 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002080 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002081
2082 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2083 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2084 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2085 ev->interp = self->interp;
2086 ev->create = 1;
2087 ev->name = cmdName;
2088 ev->data = (ClientData)data;
2089 ev->status = &err;
2090 ev->done = NULL;
2091 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2092 }
2093 else {
2094 ENTER_TCL
2095 err = Tcl_CreateCommand(
2096 Tkapp_Interp(self), cmdName, PythonCmd,
2097 (ClientData)data, PythonCmdDelete) == NULL;
2098 LEAVE_TCL
2099 }
2100 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002101 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002102 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002103 return NULL;
2104 }
Guido van Rossum18468821994-06-20 07:49:28 +00002105
Barry Warsawfa701a81997-01-16 00:15:11 +00002106 Py_INCREF(Py_None);
2107 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002108}
2109
Barry Warsawfa701a81997-01-16 00:15:11 +00002110
2111
Guido van Rossum18468821994-06-20 07:49:28 +00002112static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002113Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002114{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002115 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002116 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002117 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002118
Guido van Rossum43713e52000-02-29 13:59:29 +00002119 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002120 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002121 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2122 CommandEvent *ev;
2123 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2124 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2125 ev->interp = self->interp;
2126 ev->create = 0;
2127 ev->name = cmdName;
2128 ev->status = &err;
2129 ev->done = NULL;
2130 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2131 &command_mutex);
2132 }
2133 else {
2134 ENTER_TCL
2135 err = Tcl_DeleteCommand(self->interp, cmdName);
2136 LEAVE_TCL
2137 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002138 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002139 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2140 return NULL;
2141 }
2142 Py_INCREF(Py_None);
2143 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002144}
2145
Barry Warsawfa701a81997-01-16 00:15:11 +00002146
2147
Guido van Rossum00d93061998-05-28 23:06:38 +00002148#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002149/** File Handler **/
2150
Guido van Rossum00d93061998-05-28 23:06:38 +00002151typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002152 PyObject *func;
2153 PyObject *file;
2154 int id;
2155 struct _fhcdata *next;
2156} FileHandler_ClientData;
2157
2158static FileHandler_ClientData *HeadFHCD;
2159
2160static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002161NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002162{
2163 FileHandler_ClientData *p;
2164 p = PyMem_NEW(FileHandler_ClientData, 1);
2165 if (p != NULL) {
2166 Py_XINCREF(func);
2167 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002168 p->func = func;
2169 p->file = file;
2170 p->id = id;
2171 p->next = HeadFHCD;
2172 HeadFHCD = p;
2173 }
2174 return p;
2175}
2176
2177static void
Fred Drake509d79a2000-07-08 04:04:38 +00002178DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002179{
2180 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002181
2182 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002183 while ((p = *pp) != NULL) {
2184 if (p->id == id) {
2185 *pp = p->next;
2186 Py_XDECREF(p->func);
2187 Py_XDECREF(p->file);
2188 PyMem_DEL(p);
2189 }
2190 else
2191 pp = &p->next;
2192 }
2193}
2194
Guido van Rossuma597dde1995-01-10 20:56:29 +00002195static void
Fred Drake509d79a2000-07-08 04:04:38 +00002196FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002197{
Guido van Rossum00d93061998-05-28 23:06:38 +00002198 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002199 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002200
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002201 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002202 func = data->func;
2203 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002204
Barry Warsawfa701a81997-01-16 00:15:11 +00002205 arg = Py_BuildValue("(Oi)", file, (long) mask);
2206 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002207 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002208
2209 if (res == NULL) {
2210 errorInCmd = 1;
2211 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2212 }
2213 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002214 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002215}
2216
Guido van Rossum18468821994-06-20 07:49:28 +00002217static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002218Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2219 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002220{
Guido van Rossum00d93061998-05-28 23:06:38 +00002221 FileHandler_ClientData *data;
2222 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002223 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002224
Guido van Rossum2834b972000-10-06 16:58:26 +00002225 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2226 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002227 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002228
Martin v. Löwisa9656492003-03-30 08:44:58 +00002229#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002230 if (!self && !tcl_lock) {
2231 /* We don't have the Tcl lock since Tcl is threaded. */
2232 PyErr_SetString(PyExc_RuntimeError,
2233 "_tkinter.createfilehandler not supported "
2234 "for threaded Tcl");
2235 return NULL;
2236 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002237#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002238
2239 if (self) {
2240 CHECK_TCL_APPARTMENT;
2241 }
2242
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002243 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002244 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002245 return NULL;
2246 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002247 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002248 return NULL;
2249 }
2250
Guido van Rossuma80649b2000-03-28 20:07:05 +00002251 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002252 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002253 return NULL;
2254
Barry Warsawfa701a81997-01-16 00:15:11 +00002255 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002256 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002257 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002258 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002259 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002260 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002261}
2262
2263static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002264Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002265{
Barry Warsawfa701a81997-01-16 00:15:11 +00002266 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002267 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002268
Guido van Rossum43713e52000-02-29 13:59:29 +00002269 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002270 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002271
Martin v. Löwisa9656492003-03-30 08:44:58 +00002272#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002273 if (!self && !tcl_lock) {
2274 /* We don't have the Tcl lock since Tcl is threaded. */
2275 PyErr_SetString(PyExc_RuntimeError,
2276 "_tkinter.deletefilehandler not supported "
2277 "for threaded Tcl");
2278 return NULL;
2279 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002280#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002281
2282 if (self) {
2283 CHECK_TCL_APPARTMENT;
2284 }
2285
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002286 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002287 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002288 return NULL;
2289
Guido van Rossuma80649b2000-03-28 20:07:05 +00002290 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002291
Barry Warsawfa701a81997-01-16 00:15:11 +00002292 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002293 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002294 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002295 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002296 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002297 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002298}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002299#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002300
Barry Warsawfa701a81997-01-16 00:15:11 +00002301
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002302/**** Tktt Object (timer token) ****/
2303
Jeremy Hylton938ace62002-07-17 16:30:39 +00002304static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002305
Guido van Rossum00d93061998-05-28 23:06:38 +00002306typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002307 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002308 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002309 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002310} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002311
2312static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002313Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002314{
Barry Warsawfa701a81997-01-16 00:15:11 +00002315 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002316 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002317
Guido van Rossum43713e52000-02-29 13:59:29 +00002318 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002319 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002320 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002321 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002322 v->token = NULL;
2323 }
2324 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002325 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002326 Py_DECREF(func);
2327 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002328 }
2329 Py_INCREF(Py_None);
2330 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002331}
2332
2333static PyMethodDef Tktt_methods[] =
2334{
Neal Norwitzb0493252002-03-31 14:44:22 +00002335 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002336 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002337};
2338
2339static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002340Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002341{
Barry Warsawfa701a81997-01-16 00:15:11 +00002342 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002343
Guido van Rossumb18618d2000-05-03 23:44:39 +00002344 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002345 if (v == NULL)
2346 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002347
Guido van Rossum00d93061998-05-28 23:06:38 +00002348 Py_INCREF(func);
2349 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002350 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002351
2352 /* Extra reference, deleted when called or when handler is deleted */
2353 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002354 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002355}
2356
2357static void
Fred Drake509d79a2000-07-08 04:04:38 +00002358Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002359{
Guido van Rossum00d93061998-05-28 23:06:38 +00002360 TkttObject *v = (TkttObject *)self;
2361 PyObject *func = v->func;
2362
2363 Py_XDECREF(func);
2364
Guido van Rossumb18618d2000-05-03 23:44:39 +00002365 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002366}
2367
Guido van Rossum597ac201998-05-12 14:36:19 +00002368static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002369Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002370{
Barry Warsawfa701a81997-01-16 00:15:11 +00002371 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002372 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002373
Tim Peters885d4572001-11-28 20:27:42 +00002374 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002375 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002376 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002377}
2378
2379static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002380Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002381{
Barry Warsawfa701a81997-01-16 00:15:11 +00002382 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002383}
2384
2385static PyTypeObject Tktt_Type =
2386{
Guido van Rossum35d43371997-08-02 00:09:09 +00002387 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002388 0, /*ob_size */
2389 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002390 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002391 0, /*tp_itemsize */
2392 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002393 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002394 Tktt_GetAttr, /*tp_getattr */
2395 0, /*tp_setattr */
2396 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002397 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002398 0, /*tp_as_number */
2399 0, /*tp_as_sequence */
2400 0, /*tp_as_mapping */
2401 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002402};
2403
Barry Warsawfa701a81997-01-16 00:15:11 +00002404
2405
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002406/** Timer Handler **/
2407
2408static void
Fred Drake509d79a2000-07-08 04:04:38 +00002409TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002410{
Guido van Rossum00d93061998-05-28 23:06:38 +00002411 TkttObject *v = (TkttObject *)clientData;
2412 PyObject *func = v->func;
2413 PyObject *res;
2414
2415 if (func == NULL)
2416 return;
2417
2418 v->func = NULL;
2419
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002420 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002421
2422 res = PyEval_CallObject(func, NULL);
2423 Py_DECREF(func);
2424 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002425
Barry Warsawfa701a81997-01-16 00:15:11 +00002426 if (res == NULL) {
2427 errorInCmd = 1;
2428 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2429 }
2430 else
2431 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002432
2433 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002434}
2435
2436static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002437Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002438{
Barry Warsawfa701a81997-01-16 00:15:11 +00002439 int milliseconds;
2440 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002441 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002442
Guido van Rossum2834b972000-10-06 16:58:26 +00002443 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2444 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002445 return NULL;
2446 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002447 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002448 return NULL;
2449 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002450
Martin v. Löwisa9656492003-03-30 08:44:58 +00002451#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002452 if (!self && !tcl_lock) {
2453 /* We don't have the Tcl lock since Tcl is threaded. */
2454 PyErr_SetString(PyExc_RuntimeError,
2455 "_tkinter.createtimerhandler not supported "
2456 "for threaded Tcl");
2457 return NULL;
2458 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002459#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002460
2461 if (self) {
2462 CHECK_TCL_APPARTMENT;
2463 }
2464
Guido van Rossum00d93061998-05-28 23:06:38 +00002465 v = Tktt_New(func);
2466 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2467 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002468
Guido van Rossum00d93061998-05-28 23:06:38 +00002469 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002470}
2471
Barry Warsawfa701a81997-01-16 00:15:11 +00002472
Guido van Rossum18468821994-06-20 07:49:28 +00002473/** Event Loop **/
2474
Guido van Rossum18468821994-06-20 07:49:28 +00002475static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002476Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002477{
Barry Warsawfa701a81997-01-16 00:15:11 +00002478 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002479 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002480#ifdef WITH_THREAD
2481 PyThreadState *tstate = PyThreadState_Get();
2482#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002483
Guido van Rossum43713e52000-02-29 13:59:29 +00002484 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002485 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002486
Martin v. Löwisa9656492003-03-30 08:44:58 +00002487#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002488 if (!self && !tcl_lock) {
2489 /* We don't have the Tcl lock since Tcl is threaded. */
2490 PyErr_SetString(PyExc_RuntimeError,
2491 "_tkinter.mainloop not supported "
2492 "for threaded Tcl");
2493 return NULL;
2494 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002495#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002496
2497 if (self) {
2498 CHECK_TCL_APPARTMENT;
2499 self->dispatching = 1;
2500 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002501
Barry Warsawfa701a81997-01-16 00:15:11 +00002502 quitMainLoop = 0;
2503 while (Tk_GetNumMainWindows() > threshold &&
2504 !quitMainLoop &&
2505 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002506 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002507 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002508
2509#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002510 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002511 /* Allow other Python threads to run. */
2512 ENTER_TCL
2513 result = Tcl_DoOneEvent(0);
2514 LEAVE_TCL
2515 }
2516 else {
2517 Py_BEGIN_ALLOW_THREADS
2518 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2519 tcl_tstate = tstate;
2520 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2521 tcl_tstate = NULL;
2522 if(tcl_lock)PyThread_release_lock(tcl_lock);
2523 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002524 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002525 Py_END_ALLOW_THREADS
2526 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002527#else
2528 result = Tcl_DoOneEvent(0);
2529#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002530
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002531 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002532 if (self)
2533 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002534 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002535 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002536 if (result < 0)
2537 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002538 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002539 if (self)
2540 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002541 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002542
Barry Warsawfa701a81997-01-16 00:15:11 +00002543 if (errorInCmd) {
2544 errorInCmd = 0;
2545 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2546 excInCmd = valInCmd = trbInCmd = NULL;
2547 return NULL;
2548 }
2549 Py_INCREF(Py_None);
2550 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002551}
2552
2553static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002554Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002555{
Guido van Rossum35d43371997-08-02 00:09:09 +00002556 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002557 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002558
Guido van Rossum43713e52000-02-29 13:59:29 +00002559 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002560 return NULL;
2561
Guido van Rossum00d93061998-05-28 23:06:38 +00002562 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002563 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002564 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002565 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002566}
2567
2568static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002569Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002570{
2571
Guido van Rossum43713e52000-02-29 13:59:29 +00002572 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002573 return NULL;
2574
2575 quitMainLoop = 1;
2576 Py_INCREF(Py_None);
2577 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002578}
2579
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002580static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002581Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002582{
2583
Guido van Rossum43713e52000-02-29 13:59:29 +00002584 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002585 return NULL;
2586
2587 return PyInt_FromLong((long)Tkapp_Interp(self));
2588}
2589
Barry Warsawfa701a81997-01-16 00:15:11 +00002590
Martin v. Löwisffad6332002-11-26 09:28:05 +00002591static PyObject *
2592Tkapp_WantObjects(PyObject *self, PyObject *args)
2593{
2594
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002595 int wantobjects;
2596 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002597 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002598 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002599
2600 Py_INCREF(Py_None);
2601 return Py_None;
2602}
2603
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002604static PyObject *
2605Tkapp_WillDispatch(PyObject *self, PyObject *args)
2606{
2607
2608 ((TkappObject*)self)->dispatching = 1;
2609
2610 Py_INCREF(Py_None);
2611 return Py_None;
2612}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002613
Barry Warsawfa701a81997-01-16 00:15:11 +00002614
Guido van Rossum18468821994-06-20 07:49:28 +00002615/**** Tkapp Method List ****/
2616
2617static PyMethodDef Tkapp_methods[] =
2618{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002619 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002620 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002621 {"call", Tkapp_Call, METH_OLDARGS},
2622 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2623 {"eval", Tkapp_Eval, METH_VARARGS},
2624 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2625 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2626 {"record", Tkapp_Record, METH_VARARGS},
2627 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2628 {"setvar", Tkapp_SetVar, METH_VARARGS},
2629 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2630 {"getvar", Tkapp_GetVar, METH_VARARGS},
2631 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2632 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2633 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2634 {"getint", Tkapp_GetInt, METH_VARARGS},
2635 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2636 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2637 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2638 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2639 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2640 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2641 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2642 {"split", Tkapp_Split, METH_VARARGS},
2643 {"merge", Tkapp_Merge, METH_OLDARGS},
2644 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2645 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002646#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002647 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2648 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002649#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002650 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2651 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2652 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2653 {"quit", Tkapp_Quit, METH_VARARGS},
2654 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002655 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002656};
2657
Barry Warsawfa701a81997-01-16 00:15:11 +00002658
2659
Guido van Rossum18468821994-06-20 07:49:28 +00002660/**** Tkapp Type Methods ****/
2661
2662static void
Fred Drake509d79a2000-07-08 04:04:38 +00002663Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002664{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002665 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002666 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002667 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002668 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002669 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002670 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002671}
2672
2673static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002674Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002675{
Guido van Rossum35d43371997-08-02 00:09:09 +00002676 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002677}
2678
2679static PyTypeObject Tkapp_Type =
2680{
Guido van Rossum35d43371997-08-02 00:09:09 +00002681 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002682 0, /*ob_size */
2683 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002684 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002685 0, /*tp_itemsize */
2686 Tkapp_Dealloc, /*tp_dealloc */
2687 0, /*tp_print */
2688 Tkapp_GetAttr, /*tp_getattr */
2689 0, /*tp_setattr */
2690 0, /*tp_compare */
2691 0, /*tp_repr */
2692 0, /*tp_as_number */
2693 0, /*tp_as_sequence */
2694 0, /*tp_as_mapping */
2695 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002696};
2697
Barry Warsawfa701a81997-01-16 00:15:11 +00002698
2699
Guido van Rossum18468821994-06-20 07:49:28 +00002700/**** Tkinter Module ****/
2701
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002702typedef struct {
2703 PyObject* tuple;
2704 int size; /* current size */
2705 int maxsize; /* allocated size */
2706} FlattenContext;
2707
2708static int
2709_bump(FlattenContext* context, int size)
2710{
Guido van Rossum2834b972000-10-06 16:58:26 +00002711 /* expand tuple to hold (at least) size new items.
2712 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002713
2714 int maxsize = context->maxsize * 2;
2715
2716 if (maxsize < context->size + size)
2717 maxsize = context->size + size;
2718
2719 context->maxsize = maxsize;
2720
Tim Peters4324aa32001-05-28 22:30:08 +00002721 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002722}
2723
2724static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002725_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002726{
2727 /* add tuple or list to argument tuple (recursively) */
2728
2729 int i, size;
2730
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002731 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002732 PyErr_SetString(PyExc_ValueError,
2733 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002734 return 0;
2735 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002736 size = PyList_GET_SIZE(item);
2737 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002738 if (context->size + size > context->maxsize &&
2739 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002740 return 0;
2741 /* copy items to output tuple */
2742 for (i = 0; i < size; i++) {
2743 PyObject *o = PyList_GET_ITEM(item, i);
2744 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002745 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002746 return 0;
2747 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002748 if (context->size + 1 > context->maxsize &&
2749 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002750 return 0;
2751 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002752 PyTuple_SET_ITEM(context->tuple,
2753 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002754 }
2755 }
2756 } else if (PyTuple_Check(item)) {
2757 /* same, for tuples */
2758 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002759 if (context->size + size > context->maxsize &&
2760 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002761 return 0;
2762 for (i = 0; i < size; i++) {
2763 PyObject *o = PyTuple_GET_ITEM(item, i);
2764 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002765 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002766 return 0;
2767 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002768 if (context->size + 1 > context->maxsize &&
2769 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002770 return 0;
2771 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002772 PyTuple_SET_ITEM(context->tuple,
2773 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002774 }
2775 }
2776 } else {
2777 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2778 return 0;
2779 }
2780 return 1;
2781}
2782
2783static PyObject *
2784Tkinter_Flatten(PyObject* self, PyObject* args)
2785{
2786 FlattenContext context;
2787 PyObject* item;
2788
2789 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2790 return NULL;
2791
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002792 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002793 if (context.maxsize <= 0)
2794 return PyTuple_New(0);
2795
2796 context.tuple = PyTuple_New(context.maxsize);
2797 if (!context.tuple)
2798 return NULL;
2799
2800 context.size = 0;
2801
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002802 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002803 return NULL;
2804
Tim Peters4324aa32001-05-28 22:30:08 +00002805 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002806 return NULL;
2807
2808 return context.tuple;
2809}
2810
Guido van Rossum18468821994-06-20 07:49:28 +00002811static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002812Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002813{
Barry Warsawfa701a81997-01-16 00:15:11 +00002814 char *screenName = NULL;
2815 char *baseName = NULL;
2816 char *className = NULL;
2817 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002818 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002819
Guido van Rossum35d43371997-08-02 00:09:09 +00002820 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002821 if (baseName != NULL)
2822 baseName++;
2823 else
2824 baseName = Py_GetProgramName();
2825 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002826
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002827 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002828 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002829 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002830 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002831
Barry Warsawfa701a81997-01-16 00:15:11 +00002832 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002833 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002834}
2835
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002836static PyObject *
2837Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2838{
2839 int new_val;
2840 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2841 return NULL;
2842 if (new_val < 0) {
2843 PyErr_SetString(PyExc_ValueError,
2844 "busywaitinterval must be >= 0");
2845 return NULL;
2846 }
2847 Tkinter_busywaitinterval = new_val;
2848 Py_INCREF(Py_None);
2849 return Py_None;
2850}
2851
2852static char setbusywaitinterval_doc[] =
2853"setbusywaitinterval(n) -> None\n\
2854\n\
2855Set the busy-wait interval in milliseconds between successive\n\
2856calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2857It should be set to a divisor of the maximum time between\n\
2858frames in an animation.";
2859
2860static PyObject *
2861Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2862{
2863 return PyInt_FromLong(Tkinter_busywaitinterval);
2864}
2865
2866static char getbusywaitinterval_doc[] =
2867"getbusywaitinterval() -> int\n\
2868\n\
2869Return the current busy-wait interval between successive\n\
2870calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2871
Guido van Rossum18468821994-06-20 07:49:28 +00002872static PyMethodDef moduleMethods[] =
2873{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002874 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2875 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002876#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002877 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2878 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002879#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002880 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2881 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2882 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2883 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002884 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2885 setbusywaitinterval_doc},
2886 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2887 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002888 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002889};
2890
Guido van Rossum7bf15641998-05-22 18:28:17 +00002891#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002892
2893static int stdin_ready = 0;
2894
Guido van Rossumad4db171998-06-13 13:56:28 +00002895#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002896static void
Fred Drake509d79a2000-07-08 04:04:38 +00002897MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002898{
2899 stdin_ready = 1;
2900}
Guido van Rossumad4db171998-06-13 13:56:28 +00002901#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002902
Martin v. Löwisa9656492003-03-30 08:44:58 +00002903#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002904static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002905#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002906
Guido van Rossum18468821994-06-20 07:49:28 +00002907static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002908EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002909{
Guido van Rossumad4db171998-06-13 13:56:28 +00002910#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002911 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002912#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002913#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002914 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002915#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002916 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002917 errorInCmd = 0;
2918#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002919 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002920 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002921#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002922 while (!errorInCmd && !stdin_ready) {
2923 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002924#ifdef MS_WINDOWS
2925 if (_kbhit()) {
2926 stdin_ready = 1;
2927 break;
2928 }
2929#endif
2930#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002931 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002932 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002933 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002934
Guido van Rossum00d93061998-05-28 23:06:38 +00002935 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002936
2937 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002938 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002939 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002940 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002941 Py_END_ALLOW_THREADS
2942#else
2943 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002944#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002945
2946 if (result < 0)
2947 break;
2948 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002949#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002950 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002951#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002952 if (errorInCmd) {
2953 errorInCmd = 0;
2954 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2955 excInCmd = valInCmd = trbInCmd = NULL;
2956 PyErr_Print();
2957 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002958#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002959 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002960#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002961 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002962}
Guido van Rossum18468821994-06-20 07:49:28 +00002963
Guido van Rossum00d93061998-05-28 23:06:38 +00002964#endif
2965
Guido van Rossum7bf15641998-05-22 18:28:17 +00002966static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002967EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002968{
Guido van Rossum00d93061998-05-28 23:06:38 +00002969#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002970 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002971#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002972 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002973#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002974 PyOS_InputHook = EventHook;
2975 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002976#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002977}
2978
2979static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002980DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002981{
Guido van Rossum00d93061998-05-28 23:06:38 +00002982#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002983 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2984 PyOS_InputHook = NULL;
2985 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002986#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002987}
2988
Barry Warsawfa701a81997-01-16 00:15:11 +00002989
2990/* all errors will be checked in one fell swoop in init_tkinter() */
2991static void
Fred Drake509d79a2000-07-08 04:04:38 +00002992ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002993{
2994 PyObject *v = PyInt_FromLong(val);
2995 if (v) {
2996 PyDict_SetItemString(d, name, v);
2997 Py_DECREF(v);
2998 }
2999}
3000static void
Fred Drake509d79a2000-07-08 04:04:38 +00003001ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003002{
3003 PyObject *v = PyString_FromString(val);
3004 if (v) {
3005 PyDict_SetItemString(d, name, v);
3006 Py_DECREF(v);
3007 }
3008}
3009
3010
Mark Hammond62b1ab12002-07-23 06:31:15 +00003011PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003012init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003013{
Barry Warsawfa701a81997-01-16 00:15:11 +00003014 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003015
Barry Warsawfa701a81997-01-16 00:15:11 +00003016 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003017
3018#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003019 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003020#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003021
Barry Warsawfa701a81997-01-16 00:15:11 +00003022 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00003023
Barry Warsawfa701a81997-01-16 00:15:11 +00003024 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003025 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003026 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003027
Guido van Rossum35d43371997-08-02 00:09:09 +00003028 ins_long(d, "READABLE", TCL_READABLE);
3029 ins_long(d, "WRITABLE", TCL_WRITABLE);
3030 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3031 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3032 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3033 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3034 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3035 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3036 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003037 ins_string(d, "TK_VERSION", TK_VERSION);
3038 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003039
Guido van Rossum83551bf1997-09-13 00:44:23 +00003040 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003041
3042 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003043 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3044
Martin v. Löwisffad6332002-11-26 09:28:05 +00003045 PyTclObject_Type.ob_type = &PyType_Type;
3046 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003047
3048#ifdef TK_AQUA
3049 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3050 * start waking up. Note that Tcl_FindExecutable will do this, this
3051 * code must be above it! The original warning from
3052 * tkMacOSXAppInit.c is copied below.
3053 *
3054 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3055 * Tcl interpreter for now. It probably should work to do this
3056 * in the other order, but for now it doesn't seem to.
3057 *
3058 */
3059 Tk_MacOSXSetupTkNotifier();
3060#endif
3061
3062
Guido van Rossume187b0e2000-03-27 21:46:29 +00003063 /* This helps the dynamic loader; in Unicode aware Tcl versions
3064 it also helps Tcl find its encodings. */
3065 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003066
Barry Warsawfa701a81997-01-16 00:15:11 +00003067 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003068 return;
3069
Guido van Rossum43ff8681998-07-14 18:02:13 +00003070#if 0
3071 /* This was not a good idea; through <Destroy> bindings,
3072 Tcl_Finalize() may invoke Python code but at that point the
3073 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003074 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003075#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003076
Jack Jansen34cc5c31995-10-31 16:15:12 +00003077#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003078 /*
3079 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
3080 ** Most of the initializations in that routine (toolbox init calls and
3081 ** such) have already been done for us, so we only need these.
3082 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003083 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003084
3085 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00003086#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00003087 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00003088#endif /* GENERATINGCFM */
3089#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00003090}
Guido van Rossum9722ad81995-09-22 23:49:28 +00003091
Guido van Rossumec22c921996-02-25 04:50:29 +00003092
Barry Warsawfa701a81997-01-16 00:15:11 +00003093
Guido van Rossum9722ad81995-09-22 23:49:28 +00003094#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003095
3096/*
Guido van Rossumec22c921996-02-25 04:50:29 +00003097** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003098*/
3099
Guido van Rossum9722ad81995-09-22 23:49:28 +00003100void
3101panic(char * format, ...)
3102{
Barry Warsawfa701a81997-01-16 00:15:11 +00003103 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003104
Barry Warsawfa701a81997-01-16 00:15:11 +00003105 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003106
Guido van Rossum227cf761998-08-05 13:53:32 +00003107 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00003108 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003109
Barry Warsawfa701a81997-01-16 00:15:11 +00003110 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003111
Barry Warsawfa701a81997-01-16 00:15:11 +00003112 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00003113}
Jack Jansen40b546d1995-11-14 10:34:45 +00003114
Guido van Rossumec22c921996-02-25 04:50:29 +00003115/*
3116** Pass events to SIOUX before passing them to Tk.
3117*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003118
Guido van Rossumec22c921996-02-25 04:50:29 +00003119static int
Fred Drake509d79a2000-07-08 04:04:38 +00003120PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003121{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003122 WindowPtr frontwin;
3123 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00003124 ** Sioux eats too many events, so we don't pass it everything. We
3125 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003126 ** the Sioux window is frontmost. This means that Tk menus don't work
3127 ** in that case, but at least we can scroll the sioux window.
3128 ** Note that the SIOUXIsAppWindow() routine we use here is not really
3129 ** part of the external interface of Sioux...
3130 */
3131 frontwin = FrontWindow();
3132 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
3133 if (SIOUXHandleOneEvent(eventPtr))
3134 return 0; /* Nothing happened to the Tcl event queue */
3135 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003136 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003137}
3138
Guido van Rossumec22c921996-02-25 04:50:29 +00003139#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003140
3141/*
3142** Additional Mac specific code for dealing with shared libraries.
3143*/
3144
3145#include <Resources.h>
3146#include <CodeFragments.h>
3147
3148static int loaded_from_shlib = 0;
3149static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003150
Jack Jansen34cc5c31995-10-31 16:15:12 +00003151/*
3152** If this module is dynamically loaded the following routine should
3153** be the init routine. It takes care of adding the shared library to
3154** the resource-file chain, so that the tk routines can find their
3155** resources.
3156*/
3157OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003158init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003159{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00003160 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00003161 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003162 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003163 library_fss = *data->fragLocator.u.onDisk.fileSpec;
3164 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003165 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003166 library_fss = *data->fragLocator.u.inSegs.fileSpec;
3167 loaded_from_shlib = 1;
3168 }
3169 return noErr;
3170}
3171
3172/*
3173** Insert the library resources into the search path. Put them after
3174** the resources from the application. Again, we ignore errors.
3175*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003176static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003177mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003178{
3179 if ( !loaded_from_shlib )
3180 return;
3181 (void)FSpOpenResFile(&library_fss, fsRdPerm);
3182}
3183
Guido van Rossumec22c921996-02-25 04:50:29 +00003184#endif /* GENERATINGCFM */
3185#endif /* macintosh */