blob: 5253a106032dcce1b7adc5c66c2f6033b3cf1a1f [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000012 Only Tcl/Tk 8.2 and later are supported. Older versions are not
13 supported. (Use Python 2.2 if you cannot upgrade your Tcl/Tk
Guido van Rossuma80649b2000-03-28 20:07:05 +000014 libraries.)
15*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Guido van Rossumbf0dc9f1996-08-20 20:49:56 +000036#ifdef macintosh
37#define MAC_TCL
Guido van Rossum49b56061998-10-01 20:42:43 +000038#endif
39
Martin v. Löwis39195712003-01-04 00:33:13 +000040/* Allow using this code in Python 2.[12] */
41#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000042#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
45#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000046#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000047#endif
48
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000049#ifndef PyBool_Check
50#define PyBool_Check(o) 0
51#define PyBool_FromLong PyInt_FromLong
52#endif
53
Martin v. Löwis71e25a02002-10-01 18:08:06 +000054/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
55 making _tkinter correct for this API means to break earlier
56 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
57 earlier versions. Once Tcl releases before 8.4 don't need to be supported
58 anymore, this should go. */
59#define USE_COMPAT_CONST
60
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000061/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
62 it always; if Tcl is not threaded, the thread functions in
63 Tcl are empty. */
64#define TCL_THREADS
65
Jack Jansencb852442001-12-09 23:15:56 +000066#ifdef TK_FRAMEWORK
67#include <Tcl/tcl.h>
68#include <Tk/tk.h>
69#else
Guido van Rossum18468821994-06-20 07:49:28 +000070#include <tcl.h>
71#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000072#endif
Guido van Rossum18468821994-06-20 07:49:28 +000073
Jason Tishlerbbe89612002-12-31 20:30:46 +000074/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000075#ifndef CONST84_RETURN
76#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000077#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000078#define CONST
79#endif
80
Guido van Rossum3e819a71997-08-01 19:29:02 +000081#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
82
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000083#if TKMAJORMINOR < 8002
84#error "Tk older than 8.2 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000085#endif
86
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000087/* Unicode conversion assumes that Tcl_UniChar is two bytes.
88 We cannot test this directly, so we test UTF-8 size instead,
89 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000090 either UTF-16 or UCS-4.
91 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
92 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
93 as well.
94*/
95#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000096#error "unsupported Tcl configuration"
97#endif
98
Guido van Rossuma80649b2000-03-28 20:07:05 +000099#if defined(macintosh)
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000100/* Sigh, we have to include this to get at the tcl qd pointer */
101#include <tkMac.h>
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000102/* And this one we need to clear the menu bar */
103#include <Menus.h>
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000104#endif
105
Jack Jansen84c10b12001-07-16 19:32:52 +0000106#if !(defined(MS_WINDOWS) || defined(__CYGWIN__) || defined(macintosh))
107/* Mac has it, but it doesn't really work:-( */
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000108#define HAVE_CREATEFILEHANDLER
109#endif
110
Guido van Rossum00d93061998-05-28 23:06:38 +0000111#ifdef HAVE_CREATEFILEHANDLER
112
113/* Tcl_CreateFileHandler() changed several times; these macros deal with the
114 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
115 Unix, only because Jack added it back); when available on Windows, it only
116 applies to sockets. */
117
Guido van Rossum7bf15641998-05-22 18:28:17 +0000118#ifdef MS_WINDOWS
119#define FHANDLETYPE TCL_WIN_SOCKET
120#else
121#define FHANDLETYPE TCL_UNIX_FD
122#endif
123
Guido van Rossum00d93061998-05-28 23:06:38 +0000124/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
125 which uses this to handle Tcl events while the user is typing commands. */
126
127#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000128#define WAIT_FOR_STDIN
129#endif
130
Guido van Rossum00d93061998-05-28 23:06:38 +0000131#endif /* HAVE_CREATEFILEHANDLER */
132
Guido van Rossumad4db171998-06-13 13:56:28 +0000133#ifdef MS_WINDOWS
134#include <conio.h>
135#define WAIT_FOR_STDIN
136#endif
137
Guido van Rossum00d93061998-05-28 23:06:38 +0000138#ifdef WITH_THREAD
139
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000140/* The threading situation is complicated. Tcl is not thread-safe, except
141 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000142 So we need to use a lock around all uses of Tcl. Previously, the Python
143 interpreter lock was used for this. However, this causes problems when
144 other Python threads need to run while Tcl is blocked waiting for events.
145
146 To solve this problem, a separate lock for Tcl is introduced. Holding it
147 is incompatible with holding Python's interpreter lock. The following four
148 macros manipulate both locks together.
149
150 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
151 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
152 that could call an event handler, or otherwise affect the state of a Tcl
153 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000154 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000155 released and the lock for Tcl has been acquired.
156
Guido van Rossum5e977831998-06-15 14:03:52 +0000157 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
158 (For example, when transferring data from the Tcl interpreter result to a
159 Python string object.) This can be done by using different macros to close
160 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
161 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
162 releases the Tcl lock.
163
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000164 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000165 handlers when the handler needs to use Python. Such event handlers are
166 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000167 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000168 the Python interpreter lock, restoring the appropriate thread state, and
169 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
170 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000171 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000172
173 These locks expand to several statements and brackets; they should not be
174 used in branches of if statements and the like.
175
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000176 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
177 only valid in the thread that created it, and all Tk activity must happen in this
178 thread, also. That means that the mainloop must be invoked in the thread that
179 created the interpreter. Invoking commands from other threads is possible;
180 _tkinter will queue an event for the interpreter thread, which will then
181 execute the command and pass back the result. If the main thread is not in the
182 mainloop, and invoking commands causes an exception; if the main loop is running
183 but not processing events, the command invocation will block.
184
185 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
186 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
187 threads. So we use the Tcl TLS API.
188
Guido van Rossum00d93061998-05-28 23:06:38 +0000189*/
190
Guido van Rossum65d5b571998-12-21 19:32:43 +0000191static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000192
193#ifdef TCL_THREADS
194static Tcl_ThreadDataKey state_key;
195typedef PyThreadState *ThreadSpecificData;
196#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
197#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000198static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000199#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000200
201#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000202 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000203 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000204
205#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000206 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000207
Guido van Rossum62320c91998-06-15 04:36:09 +0000208#define ENTER_OVERLAP \
209 Py_END_ALLOW_THREADS
210
211#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000212 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000213
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000214#define ENTER_PYTHON \
215 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000216 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000217
218#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000219 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000220 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
221
222#define CHECK_TCL_APPARTMENT \
223 if (((TkappObject *)self)->threaded && \
224 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
225 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
226 return 0; \
227 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000228
229#else
230
231#define ENTER_TCL
232#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000233#define ENTER_OVERLAP
234#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000235#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000236#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000237#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000238
239#endif
240
Guido van Rossumec22c921996-02-25 04:50:29 +0000241#ifdef macintosh
242
243/*
244** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000245** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000246*/
247
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000248/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000249#define FREECAST (char *)
250
Guido van Rossumec22c921996-02-25 04:50:29 +0000251#include <Events.h> /* For EventRecord */
252
Fred Drake509d79a2000-07-08 04:04:38 +0000253typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
Guido van Rossum2834b972000-10-06 16:58:26 +0000254void Tcl_MacSetEventProc(TclMacConvertEventPtr procPtr);
255int TkMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000256
Jeremy Hylton938ace62002-07-17 16:30:39 +0000257static int PyMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000258
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000259#include <SIOUX.h>
260extern int SIOUXIsAppWindow(WindowPtr);
261
Guido van Rossumec22c921996-02-25 04:50:29 +0000262#endif /* macintosh */
263
Guido van Rossum97867b21996-08-08 19:09:53 +0000264#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000265#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000266#endif
267
Guido van Rossum18468821994-06-20 07:49:28 +0000268/**** Tkapp Object Declaration ****/
269
Jeremy Hylton938ace62002-07-17 16:30:39 +0000270static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000271
Guido van Rossum00d93061998-05-28 23:06:38 +0000272typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000273 PyObject_HEAD
274 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000275 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000276 int threaded; /* True if tcl_platform[threaded] */
277 Tcl_ThreadId thread_id;
278 int dispatching;
279 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000280 So we cache interesting types here. */
281 Tcl_ObjType *BooleanType;
282 Tcl_ObjType *ByteArrayType;
283 Tcl_ObjType *DoubleType;
284 Tcl_ObjType *IntType;
285 Tcl_ObjType *ListType;
286 Tcl_ObjType *ProcBodyType;
287 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000288} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000289
290#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000291#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000292#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000293
Guido van Rossum35d43371997-08-02 00:09:09 +0000294#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000295(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000296
Barry Warsawfa701a81997-01-16 00:15:11 +0000297
298
Guido van Rossum18468821994-06-20 07:49:28 +0000299/**** Error Handling ****/
300
301static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000302static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000303static int errorInCmd = 0;
304static PyObject *excInCmd;
305static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000306static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000307
Barry Warsawfa701a81997-01-16 00:15:11 +0000308
309
Guido van Rossum18468821994-06-20 07:49:28 +0000310static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000311Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000312{
Barry Warsawfa701a81997-01-16 00:15:11 +0000313 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
314 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000315}
316
Barry Warsawfa701a81997-01-16 00:15:11 +0000317
Barry Warsawfa701a81997-01-16 00:15:11 +0000318
Guido van Rossum18468821994-06-20 07:49:28 +0000319/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000320
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000321static int Tkinter_busywaitinterval = 20;
322
Guido van Rossum00d93061998-05-28 23:06:38 +0000323#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000324#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000325
Guido van Rossum00d93061998-05-28 23:06:38 +0000326/* Millisecond sleep() for Unix platforms. */
327
328static void
Fred Drake509d79a2000-07-08 04:04:38 +0000329Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000330{
331 /* XXX Too bad if you don't have select(). */
332 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000333 t.tv_sec = milli/1000;
334 t.tv_usec = (milli%1000) * 1000;
335 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
336}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000337#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000338
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000339/* Wait up to 1s for the mainloop to come up. */
340
341static int
342WaitForMainloop(TkappObject* self)
343{
344 int i;
345 for (i = 0; i < 10; i++) {
346 if (self->dispatching)
347 return 1;
348 Py_BEGIN_ALLOW_THREADS
349 Sleep(100);
350 Py_END_ALLOW_THREADS
351 }
352 if (self->dispatching)
353 return 1;
354 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
355 return 0;
356}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000357#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000358
Guido van Rossum00d93061998-05-28 23:06:38 +0000359
Guido van Rossum18468821994-06-20 07:49:28 +0000360static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000361AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000362{
Guido van Rossum35d43371997-08-02 00:09:09 +0000363 if (PyString_Check(value))
364 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000365#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000366 else if (PyUnicode_Check(value)) {
367 PyObject *v = PyUnicode_AsUTF8String(value);
368 if (v == NULL)
369 return NULL;
370 if (PyList_Append(tmp, v) != 0) {
371 Py_DECREF(v);
372 return NULL;
373 }
374 Py_DECREF(v);
375 return PyString_AsString(v);
376 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000377#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000378 else {
379 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000380 if (v == NULL)
381 return NULL;
382 if (PyList_Append(tmp, v) != 0) {
383 Py_DECREF(v);
384 return NULL;
385 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000386 Py_DECREF(v);
387 return PyString_AsString(v);
388 }
Guido van Rossum18468821994-06-20 07:49:28 +0000389}
390
Barry Warsawfa701a81997-01-16 00:15:11 +0000391
392
Guido van Rossum18468821994-06-20 07:49:28 +0000393#define ARGSZ 64
394
395static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000396Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000397{
Barry Warsawfa701a81997-01-16 00:15:11 +0000398 PyObject *tmp = NULL;
399 char *argvStore[ARGSZ];
400 char **argv = NULL;
401 int fvStore[ARGSZ];
402 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000403 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000404 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000405
Barry Warsawfa701a81997-01-16 00:15:11 +0000406 if (!(tmp = PyList_New(0)))
407 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000408
Barry Warsawfa701a81997-01-16 00:15:11 +0000409 argv = argvStore;
410 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000411
Barry Warsawfa701a81997-01-16 00:15:11 +0000412 if (args == NULL)
413 argc = 0;
414
415 else if (!PyTuple_Check(args)) {
416 argc = 1;
417 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000418 if (!(argv[0] = AsString(args, tmp)))
419 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000420 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000421 else {
422 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000423
Barry Warsawfa701a81997-01-16 00:15:11 +0000424 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000425 argv = (char **)ckalloc(argc * sizeof(char *));
426 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000427 if (argv == NULL || fv == NULL) {
428 PyErr_NoMemory();
429 goto finally;
430 }
431 }
432
433 for (i = 0; i < argc; i++) {
434 PyObject *v = PyTuple_GetItem(args, i);
435 if (PyTuple_Check(v)) {
436 fv[i] = 1;
437 if (!(argv[i] = Merge(v)))
438 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000439 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000440 }
441 else if (v == Py_None) {
442 argc = i;
443 break;
444 }
445 else {
446 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000447 if (!(argv[i] = AsString(v, tmp)))
448 goto finally;
449 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000450 }
451 }
Guido van Rossum18468821994-06-20 07:49:28 +0000452 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000453 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000454 if (res == NULL)
455 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000456
Barry Warsawfa701a81997-01-16 00:15:11 +0000457 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000458 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000459 if (fv[i]) {
460 ckfree(argv[i]);
461 }
462 if (argv != argvStore)
463 ckfree(FREECAST argv);
464 if (fv != fvStore)
465 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000466
Barry Warsawfa701a81997-01-16 00:15:11 +0000467 Py_DECREF(tmp);
468 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000469}
470
Barry Warsawfa701a81997-01-16 00:15:11 +0000471
472
Guido van Rossum18468821994-06-20 07:49:28 +0000473static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000474Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000475{
Barry Warsawfa701a81997-01-16 00:15:11 +0000476 int argc;
477 char **argv;
478 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000479
Barry Warsawfa701a81997-01-16 00:15:11 +0000480 if (list == NULL) {
481 Py_INCREF(Py_None);
482 return Py_None;
483 }
Guido van Rossum18468821994-06-20 07:49:28 +0000484
Guido van Rossum00d93061998-05-28 23:06:38 +0000485 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000486 /* Not a list.
487 * Could be a quoted string containing funnies, e.g. {"}.
488 * Return the string itself.
489 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000490 return PyString_FromString(list);
491 }
Guido van Rossum18468821994-06-20 07:49:28 +0000492
Barry Warsawfa701a81997-01-16 00:15:11 +0000493 if (argc == 0)
494 v = PyString_FromString("");
495 else if (argc == 1)
496 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000497 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000498 int i;
499 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000500
Barry Warsawfa701a81997-01-16 00:15:11 +0000501 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000502 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000503 Py_DECREF(v);
504 v = NULL;
505 break;
506 }
507 PyTuple_SetItem(v, i, w);
508 }
509 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000510 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000511 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000512}
513
Martin v. Löwisffad6332002-11-26 09:28:05 +0000514/* In some cases, Tcl will still return strings that are supposed to be
515 lists. SplitObj walks through a nested tuple, finding string objects that
516 need to be split. */
517
518PyObject *
519SplitObj(PyObject *arg)
520{
521 if (PyTuple_Check(arg)) {
522 int i, size;
523 PyObject *elem, *newelem, *result;
524
525 size = PyTuple_Size(arg);
526 result = NULL;
527 /* Recursively invoke SplitObj for all tuple items.
528 If this does not return a new object, no action is
529 needed. */
530 for(i = 0; i < size; i++) {
531 elem = PyTuple_GetItem(arg, i);
532 newelem = SplitObj(elem);
533 if (!newelem) {
534 Py_XDECREF(result);
535 return NULL;
536 }
537 if (!result) {
538 int k;
539 if (newelem == elem) {
540 Py_DECREF(newelem);
541 continue;
542 }
543 result = PyTuple_New(size);
544 if (!result)
545 return NULL;
546 for(k = 0; k < i; k++) {
547 elem = PyTuple_GetItem(arg, k);
548 Py_INCREF(elem);
549 PyTuple_SetItem(result, k, elem);
550 }
551 }
552 PyTuple_SetItem(result, i, newelem);
553 }
554 if (result)
555 return result;
556 /* Fall through, returning arg. */
557 }
558 else if (PyString_Check(arg)) {
559 int argc;
560 char **argv;
561 char *list = PyString_AsString(arg);
562
563 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
564 Py_INCREF(arg);
565 return arg;
566 }
567 Tcl_Free(FREECAST argv);
568 if (argc > 1)
569 return Split(PyString_AsString(arg));
570 /* Fall through, returning arg. */
571 }
572 Py_INCREF(arg);
573 return arg;
574}
Barry Warsawfa701a81997-01-16 00:15:11 +0000575
576
Guido van Rossum18468821994-06-20 07:49:28 +0000577/**** Tkapp Object ****/
578
579#ifndef WITH_APPINIT
580int
Fred Drake509d79a2000-07-08 04:04:38 +0000581Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000582{
Barry Warsawfa701a81997-01-16 00:15:11 +0000583 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000584
Barry Warsawfa701a81997-01-16 00:15:11 +0000585 main = Tk_MainWindow(interp);
586 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000587 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000588 return TCL_ERROR;
589 }
590 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000591 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000592 return TCL_ERROR;
593 }
594 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000595}
596#endif /* !WITH_APPINIT */
597
Guido van Rossum18468821994-06-20 07:49:28 +0000598
Barry Warsawfa701a81997-01-16 00:15:11 +0000599
600
601/* Initialize the Tk application; see the `main' function in
602 * `tkMain.c'.
603 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000604
Thomas Wouters58d05102000-07-24 14:43:35 +0000605static void EnableEventHook(void); /* Forward */
606static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000607
Barry Warsawfa701a81997-01-16 00:15:11 +0000608static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000609Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000610 int interactive, int wantobjects)
Barry Warsawfa701a81997-01-16 00:15:11 +0000611{
612 TkappObject *v;
613 char *argv0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000614
Guido van Rossumb18618d2000-05-03 23:44:39 +0000615 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000616 if (v == NULL)
617 return NULL;
618
619 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000620 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000621 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
622 TCL_GLOBAL_ONLY) != NULL;
623 v->thread_id = Tcl_GetCurrentThread();
624 v->dispatching = 0;
625
626#ifndef TCL_THREADS
627 if (v->threaded) {
628 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
629 Py_DECREF(v);
630 return 0;
631 }
632#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000633#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000634 if (v->threaded && tcl_lock) {
635 /* If Tcl is threaded, we don't need the lock. */
636 PyThread_free_lock(tcl_lock);
637 tcl_lock = NULL;
638 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000639#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000640
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000641 v->BooleanType = Tcl_GetObjType("boolean");
642 v->ByteArrayType = Tcl_GetObjType("bytearray");
643 v->DoubleType = Tcl_GetObjType("double");
644 v->IntType = Tcl_GetObjType("int");
645 v->ListType = Tcl_GetObjType("list");
646 v->ProcBodyType = Tcl_GetObjType("procbody");
647 v->StringType = Tcl_GetObjType("string");
648
Guido van Rossuma80649b2000-03-28 20:07:05 +0000649#if defined(macintosh)
650 /* This seems to be needed */
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000651 ClearMenuBar();
652 TkMacInitMenus(v->interp);
653#endif
Jack Jansencb852442001-12-09 23:15:56 +0000654
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000655 /* Delete the 'exit' command, which can screw things up */
656 Tcl_DeleteCommand(v->interp, "exit");
657
Barry Warsawfa701a81997-01-16 00:15:11 +0000658 if (screenName != NULL)
659 Tcl_SetVar2(v->interp, "env", "DISPLAY",
660 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000661
Barry Warsawfa701a81997-01-16 00:15:11 +0000662 if (interactive)
663 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
664 else
665 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000666
Barry Warsawfa701a81997-01-16 00:15:11 +0000667 /* This is used to get the application class for Tk 4.1 and up */
668 argv0 = (char*)ckalloc(strlen(className) + 1);
669 if (!argv0) {
670 PyErr_NoMemory();
671 Py_DECREF(v);
672 return NULL;
673 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000674
Barry Warsawfa701a81997-01-16 00:15:11 +0000675 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000676 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000677 argv0[0] = tolower(argv0[0]);
678 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
679 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000680
Barry Warsawfa701a81997-01-16 00:15:11 +0000681 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000682 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000683
Guido van Rossum7bf15641998-05-22 18:28:17 +0000684 EnableEventHook();
685
Barry Warsawfa701a81997-01-16 00:15:11 +0000686 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000687}
688
Barry Warsawfa701a81997-01-16 00:15:11 +0000689
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000690static void
691Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
692 Tcl_Condition *cond, Tcl_Mutex *mutex)
693{
694 Py_BEGIN_ALLOW_THREADS;
695 Tcl_MutexLock(mutex);
696 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
697 Tcl_ThreadAlert(self->thread_id);
698 Tcl_ConditionWait(cond, mutex, NULL);
699 Tcl_MutexUnlock(mutex);
700 Py_END_ALLOW_THREADS
701}
702
Barry Warsawfa701a81997-01-16 00:15:11 +0000703
Guido van Rossum18468821994-06-20 07:49:28 +0000704/** Tcl Eval **/
705
Martin v. Löwisffad6332002-11-26 09:28:05 +0000706typedef struct {
707 PyObject_HEAD
708 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000709 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000710} PyTclObject;
711
712staticforward PyTypeObject PyTclObject_Type;
713#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
714
715static PyObject *
716newPyTclObject(Tcl_Obj *arg)
717{
718 PyTclObject *self;
719 self = PyObject_New(PyTclObject, &PyTclObject_Type);
720 if (self == NULL)
721 return NULL;
722 Tcl_IncrRefCount(arg);
723 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000724 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000725 return (PyObject*)self;
726}
727
728static void
729PyTclObject_dealloc(PyTclObject *self)
730{
731 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000732 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000733 PyObject_Del(self);
734}
735
736static PyObject *
737PyTclObject_str(PyTclObject *self)
738{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000739 if (self->string && PyString_Check(self->string)) {
740 Py_INCREF(self->string);
741 return self->string;
742 }
743 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000744 return PyString_FromString(Tcl_GetString(self->value));
745}
746
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000747static char*
748PyTclObject_TclString(PyObject *self)
749{
750 return Tcl_GetString(((PyTclObject*)self)->value);
751}
752
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000753/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000754PyDoc_STRVAR(PyTclObject_string__doc__,
755"the string representation of this object, either as string or Unicode");
756
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000757static PyObject *
758PyTclObject_string(PyTclObject *self, void *ignored)
759{
760 char *s;
761 int i, len;
762 if (!self->string) {
763 s = Tcl_GetStringFromObj(self->value, &len);
764 for (i = 0; i < len; i++)
765 if (s[i] & 0x80)
766 break;
767#ifdef Py_USING_UNICODE
768 if (i == len)
769 /* It is an ASCII string. */
770 self->string = PyString_FromStringAndSize(s, len);
771 else {
772 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
773 if (!self->string) {
774 PyErr_Clear();
775 self->string = PyString_FromStringAndSize(s, len);
776 }
777 }
778#else
779 self->string = PyString_FromStringAndSize(s, len);
780#endif
781 if (!self->string)
782 return NULL;
783 }
784 Py_INCREF(self->string);
785 return self->string;
786}
787
788#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000789PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
790
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000791static PyObject *
792PyTclObject_unicode(PyTclObject *self, void *ignored)
793{
794 char *s;
795 int len;
796 if (self->string && PyUnicode_Check(self->string)) {
797 Py_INCREF(self->string);
798 return self->string;
799 }
800 /* XXX Could chache result if it is non-ASCII. */
801 s = Tcl_GetStringFromObj(self->value, &len);
802 return PyUnicode_DecodeUTF8(s, len, "strict");
803}
804#endif
805
Martin v. Löwisffad6332002-11-26 09:28:05 +0000806static PyObject *
807PyTclObject_repr(PyTclObject *self)
808{
809 char buf[50];
810 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
811 self->value->typePtr->name, (int)self->value);
812 return PyString_FromString(buf);
813}
814
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000815static int
816PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
817{
818 int res;
819 res = strcmp(Tcl_GetString(self->value),
820 Tcl_GetString(other->value));
821 if (res < 0) return -1;
822 if (res > 0) return 1;
823 return 0;
824}
825
Martin v. Löwis39195712003-01-04 00:33:13 +0000826PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
827
Martin v. Löwisffad6332002-11-26 09:28:05 +0000828static PyObject*
829get_typename(PyTclObject* obj, void* ignored)
830{
831 return PyString_FromString(obj->value->typePtr->name);
832}
833
Martin v. Löwis39195712003-01-04 00:33:13 +0000834
Martin v. Löwisffad6332002-11-26 09:28:05 +0000835static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000836 {"typename", (getter)get_typename, NULL, get_typename__doc__},
837 {"string", (getter)PyTclObject_string, NULL,
838 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000839 {0},
840};
841
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000842static PyMethodDef PyTclObject_methods[] = {
843 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000844 PyTclObject_unicode__doc__},
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000845 {0}
846};
847
Martin v. Löwisffad6332002-11-26 09:28:05 +0000848statichere PyTypeObject PyTclObject_Type = {
849 PyObject_HEAD_INIT(NULL)
850 0, /*ob_size*/
851 "_tkinter.Tcl_Obj", /*tp_name*/
852 sizeof(PyTclObject), /*tp_basicsize*/
853 0, /*tp_itemsize*/
854 /* methods */
855 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
856 0, /*tp_print*/
857 0, /*tp_getattr*/
858 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000859 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000860 (reprfunc)PyTclObject_repr, /*tp_repr*/
861 0, /*tp_as_number*/
862 0, /*tp_as_sequence*/
863 0, /*tp_as_mapping*/
864 0, /*tp_hash*/
865 0, /*tp_call*/
866 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000867 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000868 0, /*tp_setattro*/
869 0, /*tp_as_buffer*/
870 Py_TPFLAGS_DEFAULT, /*tp_flags*/
871 0, /*tp_doc*/
872 0, /*tp_traverse*/
873 0, /*tp_clear*/
874 0, /*tp_richcompare*/
875 0, /*tp_weaklistoffset*/
876 0, /*tp_iter*/
877 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000878 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000879 0, /*tp_members*/
880 PyTclObject_getsetlist, /*tp_getset*/
881 0, /*tp_base*/
882 0, /*tp_dict*/
883 0, /*tp_descr_get*/
884 0, /*tp_descr_set*/
885 0, /*tp_dictoffset*/
886 0, /*tp_init*/
887 0, /*tp_alloc*/
888 0, /*tp_new*/
889 0, /*tp_free*/
890 0, /*tp_is_gc*/
891};
892
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000893static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000894AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000895{
896 Tcl_Obj *result;
897
898 if (PyString_Check(value))
899 return Tcl_NewStringObj(PyString_AS_STRING(value),
900 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000901 else if (PyBool_Check(value))
902 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000903 else if (PyInt_Check(value))
904 return Tcl_NewLongObj(PyInt_AS_LONG(value));
905 else if (PyFloat_Check(value))
906 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
907 else if (PyTuple_Check(value)) {
908 Tcl_Obj **argv = (Tcl_Obj**)
909 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
910 int i;
911 if(!argv)
912 return 0;
913 for(i=0;i<PyTuple_Size(value);i++)
914 argv[i] = AsObj(PyTuple_GetItem(value,i));
915 result = Tcl_NewListObj(PyTuple_Size(value), argv);
916 ckfree(FREECAST argv);
917 return result;
918 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000919#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000920 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000921 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
922 int size = PyUnicode_GET_SIZE(value);
923 /* This #ifdef assumes that Tcl uses UCS-2.
924 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000925#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000926 Tcl_UniChar *outbuf;
927 int i;
928 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
929 if (!outbuf) {
930 PyErr_NoMemory();
931 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000932 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000933 for (i = 0; i < size; i++) {
934 if (inbuf[i] >= 0x10000) {
935 /* Tcl doesn't do UTF-16, yet. */
936 PyErr_SetString(PyExc_ValueError,
937 "unsupported character");
938 ckfree(FREECAST outbuf);
939 return NULL;
940 }
941 outbuf[i] = inbuf[i];
942 }
943 result = Tcl_NewUnicodeObj(outbuf, size);
944 ckfree(FREECAST outbuf);
945 return result;
946#else
947 return Tcl_NewUnicodeObj(inbuf, size);
948#endif
949
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000950 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000951#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000952 else if(PyTclObject_Check(value)) {
953 Tcl_Obj *v = ((PyTclObject*)value)->value;
954 Tcl_IncrRefCount(v);
955 return v;
956 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000957 else {
958 PyObject *v = PyObject_Str(value);
959 if (!v)
960 return 0;
961 result = AsObj(v);
962 Py_DECREF(v);
963 return result;
964 }
965}
966
Martin v. Löwisffad6332002-11-26 09:28:05 +0000967static PyObject*
968FromObj(PyObject* tkapp, Tcl_Obj *value)
969{
970 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000971 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000972
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000973 if (value->typePtr == NULL) {
974 /* If the result contains any bytes with the top bit set,
975 it's UTF-8 and we should decode it to Unicode */
976#ifdef Py_USING_UNICODE
977 int i;
978 char *s = value->bytes;
979 int len = value->length;
980 for (i = 0; i < len; i++) {
981 if (value->bytes[i] & 0x80)
982 break;
983 }
984
985 if (i == value->length)
986 result = PyString_FromStringAndSize(s, len);
987 else {
988 /* Convert UTF-8 to Unicode string */
989 result = PyUnicode_DecodeUTF8(s, len, "strict");
990 if (result == NULL) {
991 PyErr_Clear();
992 result = PyString_FromStringAndSize(s, len);
993 }
994 }
995#else
996 res = PyString_FromStringAndSize(value->bytes, value->length);
997#endif
998 return result;
999 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001000
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001001 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001002 result = value->internalRep.longValue ? Py_True : Py_False;
1003 Py_INCREF(result);
1004 return result;
1005 }
1006
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001007 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001008 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +00001009 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001010 return PyString_FromStringAndSize(data, size);
1011 }
1012
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001013 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001014 return PyFloat_FromDouble(value->internalRep.doubleValue);
1015 }
1016
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001017 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001018 return PyInt_FromLong(value->internalRep.longValue);
1019 }
1020
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001021 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001022 int size;
1023 int i, status;
1024 PyObject *elem;
1025 Tcl_Obj *tcl_elem;
1026
1027 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1028 if (status == TCL_ERROR)
1029 return Tkinter_Error(tkapp);
1030 result = PyTuple_New(size);
1031 if (!result)
1032 return NULL;
1033 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001034 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001035 value, i, &tcl_elem);
1036 if (status == TCL_ERROR) {
1037 Py_DECREF(result);
1038 return Tkinter_Error(tkapp);
1039 }
1040 elem = FromObj(tkapp, tcl_elem);
1041 if (!elem) {
1042 Py_DECREF(result);
1043 return NULL;
1044 }
1045 PyTuple_SetItem(result, i, elem);
1046 }
1047 return result;
1048 }
1049
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001050 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001051 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001052 }
1053
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001054 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001055#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001056#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001057 PyObject *result;
1058 int size;
1059 Tcl_UniChar *input;
1060 Py_UNICODE *output;
1061
1062 size = Tcl_GetCharLength(value);
1063 result = PyUnicode_FromUnicode(NULL, size);
1064 if (!result)
1065 return NULL;
1066 input = Tcl_GetUnicode(value);
1067 output = PyUnicode_AS_UNICODE(result);
1068 while (size--)
1069 *output++ = *input++;
1070 return result;
1071#else
1072 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1073 Tcl_GetCharLength(value));
1074#endif
1075#else
1076 int size;
1077 char *c;
1078 c = Tcl_GetStringFromObj(value, &size);
1079 return PyString_FromStringAndSize(c, size);
1080#endif
1081 }
1082
1083 return newPyTclObject(value);
1084}
1085
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001086/* This mutex synchronizes inter-thread command calls. */
1087
1088TCL_DECLARE_MUTEX(call_mutex)
1089
1090typedef struct Tkapp_CallEvent {
1091 Tcl_Event ev; /* Must be first */
1092 TkappObject *self;
1093 PyObject *args;
1094 int flags;
1095 PyObject **res;
1096 PyObject **exc_type, **exc_value, **exc_tb;
1097 Tcl_Condition done;
1098} Tkapp_CallEvent;
1099
1100void
1101Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001102{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001103 int i;
1104 for (i = 0; i < objc; i++)
1105 Tcl_DecrRefCount(objv[i]);
1106 if (objv != objStore)
1107 ckfree(FREECAST objv);
1108}
Guido van Rossum18468821994-06-20 07:49:28 +00001109
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001110/* Convert Python objects to Tcl objects. This must happen in the
1111 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001112
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001113static Tcl_Obj**
1114Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1115{
1116 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001117 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001118 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001119 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001120
Guido van Rossum212643f1998-04-29 16:22:14 +00001121 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001122 objv[0] = AsObj(args);
1123 if (objv[0] == 0)
1124 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001125 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001126 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001127 }
1128 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001129 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001130
Guido van Rossum632de272000-03-29 00:19:50 +00001131 if (objc > ARGSZ) {
1132 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1133 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001134 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001135 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001136 goto finally;
1137 }
1138 }
1139
Guido van Rossum632de272000-03-29 00:19:50 +00001140 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001141 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001142 if (v == Py_None) {
1143 objc = i;
1144 break;
1145 }
Guido van Rossum632de272000-03-29 00:19:50 +00001146 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001147 if (!objv[i]) {
1148 /* Reset objc, so it attempts to clear
1149 objects only up to i. */
1150 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001151 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001152 }
Guido van Rossum632de272000-03-29 00:19:50 +00001153 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001154 }
1155 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001156 *pobjc = objc;
1157 return objv;
1158finally:
1159 Tkapp_CallDeallocArgs(objv, objStore, objc);
1160 return NULL;
1161}
Guido van Rossum212643f1998-04-29 16:22:14 +00001162
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001163/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001164
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001165static PyObject*
1166Tkapp_CallResult(TkappObject *self)
1167{
1168 PyObject *res = NULL;
1169 if(self->wantobjects) {
1170 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001171 /* Not sure whether the IncrRef is necessary, but something
1172 may overwrite the interpreter result while we are
1173 converting it. */
1174 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001175 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001176 Tcl_DecrRefCount(value);
1177 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001178 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001179 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001180
Guido van Rossum990f5c62000-05-04 15:07:16 +00001181 /* If the result contains any bytes with the top bit set,
1182 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001183#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001184 while (*p != '\0') {
1185 if (*p & 0x80)
1186 break;
1187 p++;
1188 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001189
Guido van Rossum990f5c62000-05-04 15:07:16 +00001190 if (*p == '\0')
1191 res = PyString_FromStringAndSize(s, (int)(p-s));
1192 else {
1193 /* Convert UTF-8 to Unicode string */
1194 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001195 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1196 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001197 PyErr_Clear();
1198 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001199 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001200 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001201#else
1202 p = strchr(p, '\0');
1203 res = PyString_FromStringAndSize(s, (int)(p-s));
1204#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001205 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001206 return res;
1207}
Guido van Rossum632de272000-03-29 00:19:50 +00001208
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001209/* Tkapp_CallProc is the event procedure that is executed in the context of
1210 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1211 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001212
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001213static int
1214Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1215{
1216 Tcl_Obj *objStore[ARGSZ];
1217 Tcl_Obj **objv;
1218 int objc;
1219 int i;
1220 ENTER_PYTHON
1221 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1222 if (!objv) {
1223 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1224 *(e->res) = NULL;
1225 }
1226 LEAVE_PYTHON
1227 if (!objv)
1228 goto done;
1229 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1230 ENTER_PYTHON
1231 if (i == TCL_ERROR) {
1232 *(e->res) = NULL;
1233 *(e->exc_type) = NULL;
1234 *(e->exc_tb) = NULL;
1235 *(e->exc_value) = PyObject_CallFunction(
1236 Tkinter_TclError, "s",
1237 Tcl_GetStringResult(e->self->interp));
1238 }
1239 else {
1240 *(e->res) = Tkapp_CallResult(e->self);
1241 }
1242 LEAVE_PYTHON
1243 done:
1244 /* Wake up calling thread. */
1245 Tcl_MutexLock(&call_mutex);
1246 Tcl_ConditionNotify(&e->done);
1247 Tcl_MutexUnlock(&call_mutex);
1248 return 1;
1249}
1250
1251/* This is the main entry point for calling a Tcl command.
1252 It supports three cases, with regard to threading:
1253 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1254 the context of the calling thread.
1255 2. Tcl is threaded, caller of the command is in the interpreter thread:
1256 Execute the command in the calling thread. Since the Tcl lock will
1257 not be used, we can merge that with case 1.
1258 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1259 the interpreter thread. Allocation of Tcl objects needs to occur in the
1260 interpreter thread, so we ship the PyObject* args to the target thread,
1261 and perform processing there. */
1262
1263static PyObject *
1264Tkapp_Call(PyObject *_self, PyObject *args)
1265{
1266 Tcl_Obj *objStore[ARGSZ];
1267 Tcl_Obj **objv = NULL;
1268 int objc, i;
1269 PyObject *res = NULL;
1270 TkappObject *self = (TkappObject*)_self;
1271 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1272 int flags = TCL_EVAL_DIRECT;
1273
Martin v. Löwisa9656492003-03-30 08:44:58 +00001274#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001275 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1276 /* We cannot call the command directly. Instead, we must
1277 marshal the parameters to the interpreter thread. */
1278 Tkapp_CallEvent *ev;
1279 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001280 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001281 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001282 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1283 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1284 ev->self = self;
1285 ev->args = args;
1286 ev->res = &res;
1287 ev->exc_type = &exc_type;
1288 ev->exc_value = &exc_value;
1289 ev->exc_tb = &exc_tb;
1290 ev->done = (Tcl_Condition)0;
1291
1292 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1293
1294 if (res == NULL) {
1295 if (exc_type)
1296 PyErr_Restore(exc_type, exc_value, exc_tb);
1297 else
1298 PyErr_SetObject(Tkinter_TclError, exc_value);
1299 }
1300 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001301 else
1302#endif
1303 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001304
1305 objv = Tkapp_CallArgs(args, objStore, &objc);
1306 if (!objv)
1307 return NULL;
1308
1309 ENTER_TCL
1310
1311 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1312
1313 ENTER_OVERLAP
1314
1315 if (i == TCL_ERROR)
1316 Tkinter_Error(_self);
1317 else
1318 res = Tkapp_CallResult(self);
1319
1320 LEAVE_OVERLAP_TCL
1321
1322 Tkapp_CallDeallocArgs(objv, objStore, objc);
1323 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001324 return res;
1325}
1326
1327
1328static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001329Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001330{
Guido van Rossum212643f1998-04-29 16:22:14 +00001331 /* Could do the same here as for Tkapp_Call(), but this is not used
1332 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1333 way for the user to do what all its Global* variants do (save and
1334 reset the scope pointer, call the local version, restore the saved
1335 scope pointer). */
1336
Guido van Rossum62320c91998-06-15 04:36:09 +00001337 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001338 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001339
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001340 CHECK_TCL_APPARTMENT;
1341
Guido van Rossum62320c91998-06-15 04:36:09 +00001342 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001343 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001344 int err;
1345 ENTER_TCL
1346 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001347 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001348 if (err == TCL_ERROR)
1349 res = Tkinter_Error(self);
1350 else
1351 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001352 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001353 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001354 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001355
1356 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001357}
1358
1359static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001360Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001361{
Barry Warsawfa701a81997-01-16 00:15:11 +00001362 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001363 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001364 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001365
Guido van Rossum43713e52000-02-29 13:59:29 +00001366 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001367 return NULL;
1368
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001369 CHECK_TCL_APPARTMENT;
1370
Guido van Rossum00d93061998-05-28 23:06:38 +00001371 ENTER_TCL
1372 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001373 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001374 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001375 res = Tkinter_Error(self);
1376 else
1377 res = PyString_FromString(Tkapp_Result(self));
1378 LEAVE_OVERLAP_TCL
1379 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001380}
1381
1382static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001383Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001384{
Barry Warsawfa701a81997-01-16 00:15:11 +00001385 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001386 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001387 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001388
Guido van Rossum43713e52000-02-29 13:59:29 +00001389 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001390 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001391
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001392 CHECK_TCL_APPARTMENT;
1393
Guido van Rossum00d93061998-05-28 23:06:38 +00001394 ENTER_TCL
1395 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001396 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001397 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001398 res = Tkinter_Error(self);
1399 else
1400 res = PyString_FromString(Tkapp_Result(self));
1401 LEAVE_OVERLAP_TCL
1402 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001403}
1404
1405static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001406Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001407{
Barry Warsawfa701a81997-01-16 00:15:11 +00001408 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001409 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001410 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001411
Guido van Rossum43713e52000-02-29 13:59:29 +00001412 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001413 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001414
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001415 CHECK_TCL_APPARTMENT;
1416
Guido van Rossum00d93061998-05-28 23:06:38 +00001417 ENTER_TCL
1418 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001419 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001420 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001421 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001422
Guido van Rossum62320c91998-06-15 04:36:09 +00001423 else
1424 res = PyString_FromString(Tkapp_Result(self));
1425 LEAVE_OVERLAP_TCL
1426 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001427}
1428
1429static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001430Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001431{
Barry Warsawfa701a81997-01-16 00:15:11 +00001432 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001433 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001434 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001435
Guido van Rossum35d43371997-08-02 00:09:09 +00001436 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001437 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001438
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001439 CHECK_TCL_APPARTMENT;
1440
Guido van Rossum00d93061998-05-28 23:06:38 +00001441 ENTER_TCL
1442 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001443 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001444 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001445 res = Tkinter_Error(self);
1446 else
1447 res = PyString_FromString(Tkapp_Result(self));
1448 LEAVE_OVERLAP_TCL
1449 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001450}
1451
1452static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001453Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001454{
Barry Warsawfa701a81997-01-16 00:15:11 +00001455 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001456
Guido van Rossum43713e52000-02-29 13:59:29 +00001457 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001458 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001459 CHECK_TCL_APPARTMENT;
1460
Guido van Rossum00d93061998-05-28 23:06:38 +00001461 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001462 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001463 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001464
Barry Warsawfa701a81997-01-16 00:15:11 +00001465 Py_INCREF(Py_None);
1466 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001467}
1468
Barry Warsawfa701a81997-01-16 00:15:11 +00001469
1470
Guido van Rossum18468821994-06-20 07:49:28 +00001471/** Tcl Variable **/
1472
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001473TCL_DECLARE_MUTEX(var_mutex)
1474
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001475typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001476typedef struct VarEvent {
1477 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001478 PyObject *self;
1479 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001480 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001481 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001482 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001483 PyObject **exc_type;
1484 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001485 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486} VarEvent;
1487
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001488static int
1489varname_converter(PyObject *in, void *_out)
1490{
1491 char **out = (char**)_out;
1492 if (PyString_Check(in)) {
1493 *out = PyString_AsString(in);
1494 return 1;
1495 }
1496 if (PyTclObject_Check(in)) {
1497 *out = PyTclObject_TclString(in);
1498 return 1;
1499 }
1500 /* XXX: Should give diagnostics. */
1501 return 0;
1502}
1503
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001504void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001505var_perform(VarEvent *ev)
1506{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001507 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1508 if (!*(ev->res)) {
1509 PyObject *exc, *val, *tb;
1510 PyErr_Fetch(&exc, &val, &tb);
1511 PyErr_NormalizeException(&exc, &val, &tb);
1512 *(ev->exc_type) = exc;
1513 *(ev->exc_val) = val;
1514 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001515 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001516
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001517}
1518
1519static int
1520var_proc(VarEvent* ev, int flags)
1521{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001522 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001523 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001524 Tcl_MutexLock(&var_mutex);
1525 Tcl_ConditionNotify(&ev->cond);
1526 Tcl_MutexUnlock(&var_mutex);
1527 LEAVE_PYTHON
1528 return 1;
1529}
1530
1531static PyObject*
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001532var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001533{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001534 TkappObject *self = (TkappObject*)_self;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001535#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001537 TkappObject *self = (TkappObject*)_self;
1538 VarEvent *ev;
1539 PyObject *res, *exc_type, *exc_val;
1540
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001541 /* The current thread is not the interpreter thread. Marshal
1542 the call to the interpreter thread, then wait for
1543 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001544 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001545 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001546
1547 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1548
1549 ev->self = _self;
1550 ev->args = args;
1551 ev->flags = flags;
1552 ev->func = func;
1553 ev->res = &res;
1554 ev->exc_type = &exc_type;
1555 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001556 ev->cond = NULL;
1557 ev->ev.proc = (Tcl_EventProc*)var_proc;
1558 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001559 if (!res) {
1560 PyErr_SetObject(exc_type, exc_val);
1561 Py_DECREF(exc_type);
1562 Py_DECREF(exc_val);
1563 return NULL;
1564 }
1565 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001566 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001567#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001568 /* Tcl is not threaded, or this is the interpreter thread. */
1569 return func(_self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001570}
1571
Guido van Rossum18468821994-06-20 07:49:28 +00001572static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001573SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001574{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001575 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001576 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001577 PyObject *res = NULL;
1578 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001579
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001580 if (PyArg_ParseTuple(args, "O&O:setvar",
1581 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001582 /* XXX Acquire tcl lock??? */
1583 newval = AsObj(newValue);
1584 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001585 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001586 ENTER_TCL
1587 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1588 newval, flags);
1589 ENTER_OVERLAP
1590 if (!ok)
1591 Tkinter_Error(self);
1592 else {
1593 res = Py_None;
1594 Py_INCREF(res);
1595 }
1596 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001597 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001598 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001599 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001600 if (PyArg_ParseTuple(args, "ssO:setvar",
1601 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001602 /* XXX must hold tcl lock already??? */
1603 newval = AsObj(newValue);
1604 ENTER_TCL
1605 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1606 ENTER_OVERLAP
1607 if (!ok)
1608 Tkinter_Error(self);
1609 else {
1610 res = Py_None;
1611 Py_INCREF(res);
1612 }
1613 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001614 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001615 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001616 return NULL;
1617 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001618 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001619 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001620}
1621
1622static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001623Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001624{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001625 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001626}
1627
1628static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001629Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001630{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001631 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001632}
1633
Barry Warsawfa701a81997-01-16 00:15:11 +00001634
1635
Guido van Rossum18468821994-06-20 07:49:28 +00001636static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001637GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001638{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001639 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001640 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001641 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001642
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001643 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1644 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001645 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001646
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001647 ENTER_TCL
1648 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1649 ENTER_OVERLAP
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001650 if (((TkappObject*)self)->wantobjects) {
1651 res = FromObj(self, tres);
1652 }
1653 else {
1654 res = PyString_FromString(Tcl_GetString(tres));
1655 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001656 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001657 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001658}
1659
1660static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001661Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001662{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001663 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001664}
1665
1666static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001667Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001668{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001669 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001670}
1671
Barry Warsawfa701a81997-01-16 00:15:11 +00001672
1673
Guido van Rossum18468821994-06-20 07:49:28 +00001674static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001675UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001676{
Guido van Rossum35d43371997-08-02 00:09:09 +00001677 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001678 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001679 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001680
Guido van Rossum43713e52000-02-29 13:59:29 +00001681 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001682 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001683
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001684 ENTER_TCL
1685 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1686 ENTER_OVERLAP
1687 if (code == TCL_ERROR)
1688 res = Tkinter_Error(self);
1689 else {
1690 Py_INCREF(Py_None);
1691 res = Py_None;
1692 }
1693 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001694 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001695}
1696
1697static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001698Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001699{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001700 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001701}
1702
1703static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001704Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001705{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001706 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001707}
1708
Barry Warsawfa701a81997-01-16 00:15:11 +00001709
1710
Guido van Rossum18468821994-06-20 07:49:28 +00001711/** Tcl to Python **/
1712
1713static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001714Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001715{
Barry Warsawfa701a81997-01-16 00:15:11 +00001716 char *s;
1717 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001718
Martin v. Löwisffad6332002-11-26 09:28:05 +00001719 if (PyTuple_Size(args) == 1) {
1720 PyObject* o = PyTuple_GetItem(args, 0);
1721 if (PyInt_Check(o)) {
1722 Py_INCREF(o);
1723 return o;
1724 }
1725 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001726 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001727 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001728 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001729 return Tkinter_Error(self);
1730 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001731}
1732
1733static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001734Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001735{
Barry Warsawfa701a81997-01-16 00:15:11 +00001736 char *s;
1737 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001738
Martin v. Löwisffad6332002-11-26 09:28:05 +00001739 if (PyTuple_Size(args) == 1) {
1740 PyObject *o = PyTuple_GetItem(args, 0);
1741 if (PyFloat_Check(o)) {
1742 Py_INCREF(o);
1743 return o;
1744 }
1745 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001746 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001747 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001748 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001749 return Tkinter_Error(self);
1750 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001751}
1752
1753static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001754Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001755{
Barry Warsawfa701a81997-01-16 00:15:11 +00001756 char *s;
1757 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001758
Martin v. Löwisffad6332002-11-26 09:28:05 +00001759 if (PyTuple_Size(args) == 1) {
1760 PyObject *o = PyTuple_GetItem(args, 0);
1761 if (PyInt_Check(o)) {
1762 Py_INCREF(o);
1763 return o;
1764 }
1765 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001766 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001767 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001768 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1769 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001770 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001771}
1772
1773static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001774Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001775{
Barry Warsawfa701a81997-01-16 00:15:11 +00001776 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001777 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001778 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001779
Guido van Rossum43713e52000-02-29 13:59:29 +00001780 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001781 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001782
1783 CHECK_TCL_APPARTMENT;
1784
Guido van Rossum00d93061998-05-28 23:06:38 +00001785 ENTER_TCL
1786 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001787 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001788 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001789 res = Tkinter_Error(self);
1790 else
1791 res = Py_BuildValue("s", Tkapp_Result(self));
1792 LEAVE_OVERLAP_TCL
1793 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001794}
1795
1796static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001797Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001798{
Barry Warsawfa701a81997-01-16 00:15:11 +00001799 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001800 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001801 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001802 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001803
Guido van Rossum43713e52000-02-29 13:59:29 +00001804 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001805 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001806
1807 CHECK_TCL_APPARTMENT;
1808
Guido van Rossum00d93061998-05-28 23:06:38 +00001809 ENTER_TCL
1810 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001811 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001812 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001813 res = Tkinter_Error(self);
1814 else
1815 res = Py_BuildValue("l", v);
1816 LEAVE_OVERLAP_TCL
1817 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001818}
1819
1820static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001821Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001822{
Barry Warsawfa701a81997-01-16 00:15:11 +00001823 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001824 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001825 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001826 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001827
Guido van Rossum43713e52000-02-29 13:59:29 +00001828 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001829 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001830 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001831 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001832 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001833 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001834 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001835 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001836 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001837 res = Tkinter_Error(self);
1838 else
1839 res = Py_BuildValue("d", v);
1840 LEAVE_OVERLAP_TCL
1841 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001842}
1843
1844static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001845Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001846{
Barry Warsawfa701a81997-01-16 00:15:11 +00001847 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001848 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001849 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001850 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001851
Guido van Rossum43713e52000-02-29 13:59:29 +00001852 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001853 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001854 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001855 ENTER_TCL
1856 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001857 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001858 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001859 res = Tkinter_Error(self);
1860 else
1861 res = Py_BuildValue("i", v);
1862 LEAVE_OVERLAP_TCL
1863 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001864}
1865
Barry Warsawfa701a81997-01-16 00:15:11 +00001866
1867
Guido van Rossum18468821994-06-20 07:49:28 +00001868static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001869Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001870{
Barry Warsawfa701a81997-01-16 00:15:11 +00001871 char *list;
1872 int argc;
1873 char **argv;
1874 PyObject *v;
1875 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001876
Martin v. Löwisffad6332002-11-26 09:28:05 +00001877 if (PyTuple_Size(args) == 1) {
1878 v = PyTuple_GetItem(args, 0);
1879 if (PyTuple_Check(v)) {
1880 Py_INCREF(v);
1881 return v;
1882 }
1883 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001884 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001885 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001886
Neal Norwitzd1c55102003-05-29 00:17:03 +00001887 if (Tcl_SplitList(Tkapp_Interp(self), list,
1888 &argc, &argv) == TCL_ERROR) {
1889 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001890 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001891 }
Guido van Rossum18468821994-06-20 07:49:28 +00001892
Barry Warsawfa701a81997-01-16 00:15:11 +00001893 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001894 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001895
Barry Warsawfa701a81997-01-16 00:15:11 +00001896 for (i = 0; i < argc; i++) {
1897 PyObject *s = PyString_FromString(argv[i]);
1898 if (!s || PyTuple_SetItem(v, i, s)) {
1899 Py_DECREF(v);
1900 v = NULL;
1901 goto finally;
1902 }
1903 }
Guido van Rossum18468821994-06-20 07:49:28 +00001904
Barry Warsawfa701a81997-01-16 00:15:11 +00001905 finally:
1906 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001907 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001908 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001909}
1910
1911static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001912Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001913{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001914 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001915 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001916
Martin v. Löwisffad6332002-11-26 09:28:05 +00001917 if (PyTuple_Size(args) == 1) {
1918 PyObject* o = PyTuple_GetItem(args, 0);
1919 if (PyTuple_Check(o)) {
1920 o = SplitObj(o);
1921 return o;
1922 }
1923 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001924 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001925 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001926 v = Split(list);
1927 PyMem_Free(list);
1928 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001929}
1930
1931static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001932Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001933{
Barry Warsawfa701a81997-01-16 00:15:11 +00001934 char *s = Merge(args);
1935 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001936
Barry Warsawfa701a81997-01-16 00:15:11 +00001937 if (s) {
1938 res = PyString_FromString(s);
1939 ckfree(s);
1940 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001941
1942 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001943}
1944
Barry Warsawfa701a81997-01-16 00:15:11 +00001945
1946
Guido van Rossum18468821994-06-20 07:49:28 +00001947/** Tcl Command **/
1948
Guido van Rossum00d93061998-05-28 23:06:38 +00001949/* Client data struct */
1950typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001951 PyObject *self;
1952 PyObject *func;
1953} PythonCmd_ClientData;
1954
1955static int
Fred Drake509d79a2000-07-08 04:04:38 +00001956PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001957{
1958 errorInCmd = 1;
1959 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1960 LEAVE_PYTHON
1961 return TCL_ERROR;
1962}
1963
Guido van Rossum18468821994-06-20 07:49:28 +00001964/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001965 * function or method.
1966 */
Guido van Rossum18468821994-06-20 07:49:28 +00001967static int
Fred Drake509d79a2000-07-08 04:04:38 +00001968PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001969{
Guido van Rossum00d93061998-05-28 23:06:38 +00001970 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001971 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001972 int i, rv;
1973 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001974
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001975 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001976
Barry Warsawfa701a81997-01-16 00:15:11 +00001977 /* TBD: no error checking here since we know, via the
1978 * Tkapp_CreateCommand() that the client data is a two-tuple
1979 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001980 self = data->self;
1981 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001982
Barry Warsawfa701a81997-01-16 00:15:11 +00001983 /* Create argument list (argv1, ..., argvN) */
1984 if (!(arg = PyTuple_New(argc - 1)))
1985 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001986
Barry Warsawfa701a81997-01-16 00:15:11 +00001987 for (i = 0; i < (argc - 1); i++) {
1988 PyObject *s = PyString_FromString(argv[i + 1]);
1989 if (!s || PyTuple_SetItem(arg, i, s)) {
1990 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001991 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001992 }
1993 }
1994 res = PyEval_CallObject(func, arg);
1995 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001996
Barry Warsawfa701a81997-01-16 00:15:11 +00001997 if (res == NULL)
1998 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001999
Barry Warsawfa701a81997-01-16 00:15:11 +00002000 if (!(tmp = PyList_New(0))) {
2001 Py_DECREF(res);
2002 return PythonCmd_Error(interp);
2003 }
2004
Guido van Rossum2834b972000-10-06 16:58:26 +00002005 s = AsString(res, tmp);
2006 if (s == NULL) {
2007 rv = PythonCmd_Error(interp);
2008 }
2009 else {
2010 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
2011 rv = TCL_OK;
2012 }
2013
Barry Warsawfa701a81997-01-16 00:15:11 +00002014 Py_DECREF(res);
2015 Py_DECREF(tmp);
2016
Guido van Rossum00d93061998-05-28 23:06:38 +00002017 LEAVE_PYTHON
2018
Guido van Rossum2834b972000-10-06 16:58:26 +00002019 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002020}
2021
2022static void
Fred Drake509d79a2000-07-08 04:04:38 +00002023PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002024{
Guido van Rossum00d93061998-05-28 23:06:38 +00002025 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2026
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002027 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002028 Py_XDECREF(data->self);
2029 Py_XDECREF(data->func);
2030 PyMem_DEL(data);
2031 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002032}
2033
Barry Warsawfa701a81997-01-16 00:15:11 +00002034
2035
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002036
2037TCL_DECLARE_MUTEX(command_mutex)
2038
2039typedef struct CommandEvent{
2040 Tcl_Event ev;
2041 Tcl_Interp* interp;
2042 char *name;
2043 int create;
2044 int *status;
2045 ClientData *data;
2046 Tcl_Condition done;
2047} CommandEvent;
2048
2049static int
2050Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002051{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002052 if (ev->create)
2053 *ev->status = Tcl_CreateCommand(
2054 ev->interp, ev->name, PythonCmd,
2055 ev->data, PythonCmdDelete) == NULL;
2056 else
2057 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2058 Tcl_MutexLock(&command_mutex);
2059 Tcl_ConditionNotify(&ev->done);
2060 Tcl_MutexUnlock(&command_mutex);
2061 return 1;
2062}
2063
2064static PyObject *
2065Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2066{
2067 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002068 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002069 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002070 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002071 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002072
Guido van Rossum43713e52000-02-29 13:59:29 +00002073 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002074 return NULL;
2075 if (!PyCallable_Check(func)) {
2076 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002077 return NULL;
2078 }
Guido van Rossum18468821994-06-20 07:49:28 +00002079
Martin v. Löwisa9656492003-03-30 08:44:58 +00002080#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002081 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002082 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002083 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002084#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002085
Guido van Rossum00d93061998-05-28 23:06:38 +00002086 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002087 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002088 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002089 Py_XINCREF(self);
2090 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002091 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002092 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002093
2094 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2095 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2096 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2097 ev->interp = self->interp;
2098 ev->create = 1;
2099 ev->name = cmdName;
2100 ev->data = (ClientData)data;
2101 ev->status = &err;
2102 ev->done = NULL;
2103 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2104 }
2105 else {
2106 ENTER_TCL
2107 err = Tcl_CreateCommand(
2108 Tkapp_Interp(self), cmdName, PythonCmd,
2109 (ClientData)data, PythonCmdDelete) == NULL;
2110 LEAVE_TCL
2111 }
2112 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002113 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002114 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002115 return NULL;
2116 }
Guido van Rossum18468821994-06-20 07:49:28 +00002117
Barry Warsawfa701a81997-01-16 00:15:11 +00002118 Py_INCREF(Py_None);
2119 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002120}
2121
Barry Warsawfa701a81997-01-16 00:15:11 +00002122
2123
Guido van Rossum18468821994-06-20 07:49:28 +00002124static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002125Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002126{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002127 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002128 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002129 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002130
Guido van Rossum43713e52000-02-29 13:59:29 +00002131 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002132 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002133 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2134 CommandEvent *ev;
2135 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2136 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2137 ev->interp = self->interp;
2138 ev->create = 0;
2139 ev->name = cmdName;
2140 ev->status = &err;
2141 ev->done = NULL;
2142 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2143 &command_mutex);
2144 }
2145 else {
2146 ENTER_TCL
2147 err = Tcl_DeleteCommand(self->interp, cmdName);
2148 LEAVE_TCL
2149 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002150 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002151 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2152 return NULL;
2153 }
2154 Py_INCREF(Py_None);
2155 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002156}
2157
Barry Warsawfa701a81997-01-16 00:15:11 +00002158
2159
Guido van Rossum00d93061998-05-28 23:06:38 +00002160#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002161/** File Handler **/
2162
Guido van Rossum00d93061998-05-28 23:06:38 +00002163typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002164 PyObject *func;
2165 PyObject *file;
2166 int id;
2167 struct _fhcdata *next;
2168} FileHandler_ClientData;
2169
2170static FileHandler_ClientData *HeadFHCD;
2171
2172static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002173NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002174{
2175 FileHandler_ClientData *p;
2176 p = PyMem_NEW(FileHandler_ClientData, 1);
2177 if (p != NULL) {
2178 Py_XINCREF(func);
2179 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002180 p->func = func;
2181 p->file = file;
2182 p->id = id;
2183 p->next = HeadFHCD;
2184 HeadFHCD = p;
2185 }
2186 return p;
2187}
2188
2189static void
Fred Drake509d79a2000-07-08 04:04:38 +00002190DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002191{
2192 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002193
2194 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002195 while ((p = *pp) != NULL) {
2196 if (p->id == id) {
2197 *pp = p->next;
2198 Py_XDECREF(p->func);
2199 Py_XDECREF(p->file);
2200 PyMem_DEL(p);
2201 }
2202 else
2203 pp = &p->next;
2204 }
2205}
2206
Guido van Rossuma597dde1995-01-10 20:56:29 +00002207static void
Fred Drake509d79a2000-07-08 04:04:38 +00002208FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002209{
Guido van Rossum00d93061998-05-28 23:06:38 +00002210 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002211 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002212
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002213 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002214 func = data->func;
2215 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002216
Barry Warsawfa701a81997-01-16 00:15:11 +00002217 arg = Py_BuildValue("(Oi)", file, (long) mask);
2218 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002219 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002220
2221 if (res == NULL) {
2222 errorInCmd = 1;
2223 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2224 }
2225 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002226 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002227}
2228
Guido van Rossum18468821994-06-20 07:49:28 +00002229static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002230Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2231 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002232{
Guido van Rossum00d93061998-05-28 23:06:38 +00002233 FileHandler_ClientData *data;
2234 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002235 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002236
Guido van Rossum2834b972000-10-06 16:58:26 +00002237 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2238 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002239 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002240
Martin v. Löwisa9656492003-03-30 08:44:58 +00002241#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002242 if (!self && !tcl_lock) {
2243 /* We don't have the Tcl lock since Tcl is threaded. */
2244 PyErr_SetString(PyExc_RuntimeError,
2245 "_tkinter.createfilehandler not supported "
2246 "for threaded Tcl");
2247 return NULL;
2248 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002249#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002250
2251 if (self) {
2252 CHECK_TCL_APPARTMENT;
2253 }
2254
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002255 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002256 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002257 return NULL;
2258 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002259 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002260 return NULL;
2261 }
2262
Guido van Rossuma80649b2000-03-28 20:07:05 +00002263 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002264 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002265 return NULL;
2266
Barry Warsawfa701a81997-01-16 00:15:11 +00002267 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002268 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002269 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002270 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002271 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002272 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002273}
2274
2275static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002276Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002277{
Barry Warsawfa701a81997-01-16 00:15:11 +00002278 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002279 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002280
Guido van Rossum43713e52000-02-29 13:59:29 +00002281 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002282 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002283
Martin v. Löwisa9656492003-03-30 08:44:58 +00002284#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002285 if (!self && !tcl_lock) {
2286 /* We don't have the Tcl lock since Tcl is threaded. */
2287 PyErr_SetString(PyExc_RuntimeError,
2288 "_tkinter.deletefilehandler not supported "
2289 "for threaded Tcl");
2290 return NULL;
2291 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002292#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002293
2294 if (self) {
2295 CHECK_TCL_APPARTMENT;
2296 }
2297
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002298 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002299 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002300 return NULL;
2301
Guido van Rossuma80649b2000-03-28 20:07:05 +00002302 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002303
Barry Warsawfa701a81997-01-16 00:15:11 +00002304 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002305 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002306 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002307 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002308 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002309 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002310}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002311#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002312
Barry Warsawfa701a81997-01-16 00:15:11 +00002313
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002314/**** Tktt Object (timer token) ****/
2315
Jeremy Hylton938ace62002-07-17 16:30:39 +00002316static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002317
Guido van Rossum00d93061998-05-28 23:06:38 +00002318typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002319 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002320 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002321 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002322} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002323
2324static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002325Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002326{
Barry Warsawfa701a81997-01-16 00:15:11 +00002327 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002328 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002329
Guido van Rossum43713e52000-02-29 13:59:29 +00002330 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002331 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002332 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002333 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002334 v->token = NULL;
2335 }
2336 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002337 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002338 Py_DECREF(func);
2339 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002340 }
2341 Py_INCREF(Py_None);
2342 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002343}
2344
2345static PyMethodDef Tktt_methods[] =
2346{
Neal Norwitzb0493252002-03-31 14:44:22 +00002347 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002348 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002349};
2350
2351static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002352Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002353{
Barry Warsawfa701a81997-01-16 00:15:11 +00002354 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002355
Guido van Rossumb18618d2000-05-03 23:44:39 +00002356 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002357 if (v == NULL)
2358 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002359
Guido van Rossum00d93061998-05-28 23:06:38 +00002360 Py_INCREF(func);
2361 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002362 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002363
2364 /* Extra reference, deleted when called or when handler is deleted */
2365 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002366 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002367}
2368
2369static void
Fred Drake509d79a2000-07-08 04:04:38 +00002370Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002371{
Guido van Rossum00d93061998-05-28 23:06:38 +00002372 TkttObject *v = (TkttObject *)self;
2373 PyObject *func = v->func;
2374
2375 Py_XDECREF(func);
2376
Guido van Rossumb18618d2000-05-03 23:44:39 +00002377 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002378}
2379
Guido van Rossum597ac201998-05-12 14:36:19 +00002380static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002381Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002382{
Barry Warsawfa701a81997-01-16 00:15:11 +00002383 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002384 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002385
Tim Peters885d4572001-11-28 20:27:42 +00002386 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002387 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002388 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002389}
2390
2391static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002392Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002393{
Barry Warsawfa701a81997-01-16 00:15:11 +00002394 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002395}
2396
2397static PyTypeObject Tktt_Type =
2398{
Guido van Rossum35d43371997-08-02 00:09:09 +00002399 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002400 0, /*ob_size */
2401 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002402 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002403 0, /*tp_itemsize */
2404 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002405 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002406 Tktt_GetAttr, /*tp_getattr */
2407 0, /*tp_setattr */
2408 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002409 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002410 0, /*tp_as_number */
2411 0, /*tp_as_sequence */
2412 0, /*tp_as_mapping */
2413 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002414};
2415
Barry Warsawfa701a81997-01-16 00:15:11 +00002416
2417
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002418/** Timer Handler **/
2419
2420static void
Fred Drake509d79a2000-07-08 04:04:38 +00002421TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002422{
Guido van Rossum00d93061998-05-28 23:06:38 +00002423 TkttObject *v = (TkttObject *)clientData;
2424 PyObject *func = v->func;
2425 PyObject *res;
2426
2427 if (func == NULL)
2428 return;
2429
2430 v->func = NULL;
2431
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002432 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002433
2434 res = PyEval_CallObject(func, NULL);
2435 Py_DECREF(func);
2436 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002437
Barry Warsawfa701a81997-01-16 00:15:11 +00002438 if (res == NULL) {
2439 errorInCmd = 1;
2440 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2441 }
2442 else
2443 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002444
2445 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002446}
2447
2448static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002449Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002450{
Barry Warsawfa701a81997-01-16 00:15:11 +00002451 int milliseconds;
2452 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002453 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002454
Guido van Rossum2834b972000-10-06 16:58:26 +00002455 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2456 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002457 return NULL;
2458 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002459 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002460 return NULL;
2461 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002462
Martin v. Löwisa9656492003-03-30 08:44:58 +00002463#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002464 if (!self && !tcl_lock) {
2465 /* We don't have the Tcl lock since Tcl is threaded. */
2466 PyErr_SetString(PyExc_RuntimeError,
2467 "_tkinter.createtimerhandler not supported "
2468 "for threaded Tcl");
2469 return NULL;
2470 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002471#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002472
2473 if (self) {
2474 CHECK_TCL_APPARTMENT;
2475 }
2476
Guido van Rossum00d93061998-05-28 23:06:38 +00002477 v = Tktt_New(func);
2478 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2479 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002480
Guido van Rossum00d93061998-05-28 23:06:38 +00002481 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002482}
2483
Barry Warsawfa701a81997-01-16 00:15:11 +00002484
Guido van Rossum18468821994-06-20 07:49:28 +00002485/** Event Loop **/
2486
Guido van Rossum18468821994-06-20 07:49:28 +00002487static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002488Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002489{
Barry Warsawfa701a81997-01-16 00:15:11 +00002490 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002491 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002492#ifdef WITH_THREAD
2493 PyThreadState *tstate = PyThreadState_Get();
2494#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002495
Guido van Rossum43713e52000-02-29 13:59:29 +00002496 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002497 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002498
Martin v. Löwisa9656492003-03-30 08:44:58 +00002499#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002500 if (!self && !tcl_lock) {
2501 /* We don't have the Tcl lock since Tcl is threaded. */
2502 PyErr_SetString(PyExc_RuntimeError,
2503 "_tkinter.mainloop not supported "
2504 "for threaded Tcl");
2505 return NULL;
2506 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002507#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002508
2509 if (self) {
2510 CHECK_TCL_APPARTMENT;
2511 self->dispatching = 1;
2512 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002513
Barry Warsawfa701a81997-01-16 00:15:11 +00002514 quitMainLoop = 0;
2515 while (Tk_GetNumMainWindows() > threshold &&
2516 !quitMainLoop &&
2517 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002518 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002519 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002520
2521#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002522 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002523 /* Allow other Python threads to run. */
2524 ENTER_TCL
2525 result = Tcl_DoOneEvent(0);
2526 LEAVE_TCL
2527 }
2528 else {
2529 Py_BEGIN_ALLOW_THREADS
2530 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2531 tcl_tstate = tstate;
2532 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2533 tcl_tstate = NULL;
2534 if(tcl_lock)PyThread_release_lock(tcl_lock);
2535 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002536 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002537 Py_END_ALLOW_THREADS
2538 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002539#else
2540 result = Tcl_DoOneEvent(0);
2541#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002542
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002543 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002544 if (self)
2545 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002546 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002547 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002548 if (result < 0)
2549 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002550 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002551 if (self)
2552 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002553 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002554
Barry Warsawfa701a81997-01-16 00:15:11 +00002555 if (errorInCmd) {
2556 errorInCmd = 0;
2557 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2558 excInCmd = valInCmd = trbInCmd = NULL;
2559 return NULL;
2560 }
2561 Py_INCREF(Py_None);
2562 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002563}
2564
2565static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002566Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002567{
Guido van Rossum35d43371997-08-02 00:09:09 +00002568 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002569 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002570
Guido van Rossum43713e52000-02-29 13:59:29 +00002571 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002572 return NULL;
2573
Guido van Rossum00d93061998-05-28 23:06:38 +00002574 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002575 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002576 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002577 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002578}
2579
2580static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002581Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002582{
2583
Guido van Rossum43713e52000-02-29 13:59:29 +00002584 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002585 return NULL;
2586
2587 quitMainLoop = 1;
2588 Py_INCREF(Py_None);
2589 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002590}
2591
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002592static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002593Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002594{
2595
Guido van Rossum43713e52000-02-29 13:59:29 +00002596 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002597 return NULL;
2598
2599 return PyInt_FromLong((long)Tkapp_Interp(self));
2600}
2601
Barry Warsawfa701a81997-01-16 00:15:11 +00002602
Martin v. Löwisffad6332002-11-26 09:28:05 +00002603static PyObject *
2604Tkapp_WantObjects(PyObject *self, PyObject *args)
2605{
2606
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002607 int wantobjects = -1;
2608 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002609 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002610 if (wantobjects == -1)
2611 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002612 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002613
2614 Py_INCREF(Py_None);
2615 return Py_None;
2616}
2617
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002618static PyObject *
2619Tkapp_WillDispatch(PyObject *self, PyObject *args)
2620{
2621
2622 ((TkappObject*)self)->dispatching = 1;
2623
2624 Py_INCREF(Py_None);
2625 return Py_None;
2626}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002627
Barry Warsawfa701a81997-01-16 00:15:11 +00002628
Guido van Rossum18468821994-06-20 07:49:28 +00002629/**** Tkapp Method List ****/
2630
2631static PyMethodDef Tkapp_methods[] =
2632{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002633 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002634 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002635 {"call", Tkapp_Call, METH_OLDARGS},
2636 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2637 {"eval", Tkapp_Eval, METH_VARARGS},
2638 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2639 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2640 {"record", Tkapp_Record, METH_VARARGS},
2641 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2642 {"setvar", Tkapp_SetVar, METH_VARARGS},
2643 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2644 {"getvar", Tkapp_GetVar, METH_VARARGS},
2645 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2646 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2647 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2648 {"getint", Tkapp_GetInt, METH_VARARGS},
2649 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2650 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2651 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2652 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2653 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2654 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2655 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2656 {"split", Tkapp_Split, METH_VARARGS},
2657 {"merge", Tkapp_Merge, METH_OLDARGS},
2658 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2659 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002660#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002661 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2662 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002663#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002664 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2665 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2666 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2667 {"quit", Tkapp_Quit, METH_VARARGS},
2668 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002669 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002670};
2671
Barry Warsawfa701a81997-01-16 00:15:11 +00002672
2673
Guido van Rossum18468821994-06-20 07:49:28 +00002674/**** Tkapp Type Methods ****/
2675
2676static void
Fred Drake509d79a2000-07-08 04:04:38 +00002677Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002678{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002679 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002680 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002681 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002682 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002683 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002684 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002685}
2686
2687static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002688Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002689{
Guido van Rossum35d43371997-08-02 00:09:09 +00002690 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002691}
2692
2693static PyTypeObject Tkapp_Type =
2694{
Guido van Rossum35d43371997-08-02 00:09:09 +00002695 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002696 0, /*ob_size */
2697 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002698 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002699 0, /*tp_itemsize */
2700 Tkapp_Dealloc, /*tp_dealloc */
2701 0, /*tp_print */
2702 Tkapp_GetAttr, /*tp_getattr */
2703 0, /*tp_setattr */
2704 0, /*tp_compare */
2705 0, /*tp_repr */
2706 0, /*tp_as_number */
2707 0, /*tp_as_sequence */
2708 0, /*tp_as_mapping */
2709 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002710};
2711
Barry Warsawfa701a81997-01-16 00:15:11 +00002712
2713
Guido van Rossum18468821994-06-20 07:49:28 +00002714/**** Tkinter Module ****/
2715
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002716typedef struct {
2717 PyObject* tuple;
2718 int size; /* current size */
2719 int maxsize; /* allocated size */
2720} FlattenContext;
2721
2722static int
2723_bump(FlattenContext* context, int size)
2724{
Guido van Rossum2834b972000-10-06 16:58:26 +00002725 /* expand tuple to hold (at least) size new items.
2726 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002727
2728 int maxsize = context->maxsize * 2;
2729
2730 if (maxsize < context->size + size)
2731 maxsize = context->size + size;
2732
2733 context->maxsize = maxsize;
2734
Tim Peters4324aa32001-05-28 22:30:08 +00002735 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002736}
2737
2738static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002739_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002740{
2741 /* add tuple or list to argument tuple (recursively) */
2742
2743 int i, size;
2744
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002745 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002746 PyErr_SetString(PyExc_ValueError,
2747 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002748 return 0;
2749 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002750 size = PyList_GET_SIZE(item);
2751 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002752 if (context->size + size > context->maxsize &&
2753 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002754 return 0;
2755 /* copy items to output tuple */
2756 for (i = 0; i < size; i++) {
2757 PyObject *o = PyList_GET_ITEM(item, i);
2758 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002759 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002760 return 0;
2761 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002762 if (context->size + 1 > context->maxsize &&
2763 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002764 return 0;
2765 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002766 PyTuple_SET_ITEM(context->tuple,
2767 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002768 }
2769 }
2770 } else if (PyTuple_Check(item)) {
2771 /* same, for tuples */
2772 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002773 if (context->size + size > context->maxsize &&
2774 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002775 return 0;
2776 for (i = 0; i < size; i++) {
2777 PyObject *o = PyTuple_GET_ITEM(item, i);
2778 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002779 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002780 return 0;
2781 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002782 if (context->size + 1 > context->maxsize &&
2783 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002784 return 0;
2785 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002786 PyTuple_SET_ITEM(context->tuple,
2787 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002788 }
2789 }
2790 } else {
2791 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2792 return 0;
2793 }
2794 return 1;
2795}
2796
2797static PyObject *
2798Tkinter_Flatten(PyObject* self, PyObject* args)
2799{
2800 FlattenContext context;
2801 PyObject* item;
2802
2803 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2804 return NULL;
2805
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002806 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002807 if (context.maxsize <= 0)
2808 return PyTuple_New(0);
2809
2810 context.tuple = PyTuple_New(context.maxsize);
2811 if (!context.tuple)
2812 return NULL;
2813
2814 context.size = 0;
2815
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002816 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002817 return NULL;
2818
Tim Peters4324aa32001-05-28 22:30:08 +00002819 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002820 return NULL;
2821
2822 return context.tuple;
2823}
2824
Guido van Rossum18468821994-06-20 07:49:28 +00002825static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002826Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002827{
Barry Warsawfa701a81997-01-16 00:15:11 +00002828 char *screenName = NULL;
2829 char *baseName = NULL;
2830 char *className = NULL;
2831 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002832 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002833
Guido van Rossum35d43371997-08-02 00:09:09 +00002834 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002835 if (baseName != NULL)
2836 baseName++;
2837 else
2838 baseName = Py_GetProgramName();
2839 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002840
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002841 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002842 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002843 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002844 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002845
Barry Warsawfa701a81997-01-16 00:15:11 +00002846 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002847 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002848}
2849
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002850static PyObject *
2851Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2852{
2853 int new_val;
2854 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2855 return NULL;
2856 if (new_val < 0) {
2857 PyErr_SetString(PyExc_ValueError,
2858 "busywaitinterval must be >= 0");
2859 return NULL;
2860 }
2861 Tkinter_busywaitinterval = new_val;
2862 Py_INCREF(Py_None);
2863 return Py_None;
2864}
2865
2866static char setbusywaitinterval_doc[] =
2867"setbusywaitinterval(n) -> None\n\
2868\n\
2869Set the busy-wait interval in milliseconds between successive\n\
2870calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2871It should be set to a divisor of the maximum time between\n\
2872frames in an animation.";
2873
2874static PyObject *
2875Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2876{
2877 return PyInt_FromLong(Tkinter_busywaitinterval);
2878}
2879
2880static char getbusywaitinterval_doc[] =
2881"getbusywaitinterval() -> int\n\
2882\n\
2883Return the current busy-wait interval between successive\n\
2884calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2885
Guido van Rossum18468821994-06-20 07:49:28 +00002886static PyMethodDef moduleMethods[] =
2887{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002888 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2889 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002890#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002891 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2892 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002893#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002894 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2895 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2896 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2897 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002898 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2899 setbusywaitinterval_doc},
2900 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2901 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002902 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002903};
2904
Guido van Rossum7bf15641998-05-22 18:28:17 +00002905#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002906
2907static int stdin_ready = 0;
2908
Guido van Rossumad4db171998-06-13 13:56:28 +00002909#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002910static void
Fred Drake509d79a2000-07-08 04:04:38 +00002911MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002912{
2913 stdin_ready = 1;
2914}
Guido van Rossumad4db171998-06-13 13:56:28 +00002915#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002916
Martin v. Löwisa9656492003-03-30 08:44:58 +00002917#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002918static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002919#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002920
Guido van Rossum18468821994-06-20 07:49:28 +00002921static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002922EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002923{
Guido van Rossumad4db171998-06-13 13:56:28 +00002924#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002925 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002926#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002927#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002928 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002929#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002930 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002931 errorInCmd = 0;
2932#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002933 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002934 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002935#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002936 while (!errorInCmd && !stdin_ready) {
2937 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002938#ifdef MS_WINDOWS
2939 if (_kbhit()) {
2940 stdin_ready = 1;
2941 break;
2942 }
2943#endif
2944#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002945 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002946 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002947 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002948
Guido van Rossum00d93061998-05-28 23:06:38 +00002949 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002950
2951 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002952 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002953 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002954 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002955 Py_END_ALLOW_THREADS
2956#else
2957 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002958#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002959
2960 if (result < 0)
2961 break;
2962 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002963#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002964 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002965#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002966 if (errorInCmd) {
2967 errorInCmd = 0;
2968 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2969 excInCmd = valInCmd = trbInCmd = NULL;
2970 PyErr_Print();
2971 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002972#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002973 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002974#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002975 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002976}
Guido van Rossum18468821994-06-20 07:49:28 +00002977
Guido van Rossum00d93061998-05-28 23:06:38 +00002978#endif
2979
Guido van Rossum7bf15641998-05-22 18:28:17 +00002980static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002981EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002982{
Guido van Rossum00d93061998-05-28 23:06:38 +00002983#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002984 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002985#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002986 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002987#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002988 PyOS_InputHook = EventHook;
2989 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002990#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002991}
2992
2993static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002994DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002995{
Guido van Rossum00d93061998-05-28 23:06:38 +00002996#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002997 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2998 PyOS_InputHook = NULL;
2999 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003000#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003001}
3002
Barry Warsawfa701a81997-01-16 00:15:11 +00003003
3004/* all errors will be checked in one fell swoop in init_tkinter() */
3005static void
Fred Drake509d79a2000-07-08 04:04:38 +00003006ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003007{
3008 PyObject *v = PyInt_FromLong(val);
3009 if (v) {
3010 PyDict_SetItemString(d, name, v);
3011 Py_DECREF(v);
3012 }
3013}
3014static void
Fred Drake509d79a2000-07-08 04:04:38 +00003015ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003016{
3017 PyObject *v = PyString_FromString(val);
3018 if (v) {
3019 PyDict_SetItemString(d, name, v);
3020 Py_DECREF(v);
3021 }
3022}
3023
3024
Mark Hammond62b1ab12002-07-23 06:31:15 +00003025PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003026init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003027{
Barry Warsawfa701a81997-01-16 00:15:11 +00003028 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003029
Barry Warsawfa701a81997-01-16 00:15:11 +00003030 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003031
3032#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003033 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003034#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003035
Barry Warsawfa701a81997-01-16 00:15:11 +00003036 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00003037
Barry Warsawfa701a81997-01-16 00:15:11 +00003038 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003039 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003040 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003041
Guido van Rossum35d43371997-08-02 00:09:09 +00003042 ins_long(d, "READABLE", TCL_READABLE);
3043 ins_long(d, "WRITABLE", TCL_WRITABLE);
3044 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3045 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3046 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3047 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3048 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3049 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3050 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003051 ins_string(d, "TK_VERSION", TK_VERSION);
3052 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003053
Guido van Rossum83551bf1997-09-13 00:44:23 +00003054 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003055
3056 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003057 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3058
Martin v. Löwisffad6332002-11-26 09:28:05 +00003059 PyTclObject_Type.ob_type = &PyType_Type;
3060 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003061
3062#ifdef TK_AQUA
3063 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3064 * start waking up. Note that Tcl_FindExecutable will do this, this
3065 * code must be above it! The original warning from
3066 * tkMacOSXAppInit.c is copied below.
3067 *
3068 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3069 * Tcl interpreter for now. It probably should work to do this
3070 * in the other order, but for now it doesn't seem to.
3071 *
3072 */
3073 Tk_MacOSXSetupTkNotifier();
3074#endif
3075
3076
Guido van Rossume187b0e2000-03-27 21:46:29 +00003077 /* This helps the dynamic loader; in Unicode aware Tcl versions
3078 it also helps Tcl find its encodings. */
3079 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003080
Barry Warsawfa701a81997-01-16 00:15:11 +00003081 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003082 return;
3083
Guido van Rossum43ff8681998-07-14 18:02:13 +00003084#if 0
3085 /* This was not a good idea; through <Destroy> bindings,
3086 Tcl_Finalize() may invoke Python code but at that point the
3087 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003088 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003089#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003090
Jack Jansen34cc5c31995-10-31 16:15:12 +00003091#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003092 /*
3093 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
3094 ** Most of the initializations in that routine (toolbox init calls and
3095 ** such) have already been done for us, so we only need these.
3096 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003097 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003098
3099 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00003100#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00003101 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00003102#endif /* GENERATINGCFM */
3103#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00003104}
Guido van Rossum9722ad81995-09-22 23:49:28 +00003105
Guido van Rossumec22c921996-02-25 04:50:29 +00003106
Barry Warsawfa701a81997-01-16 00:15:11 +00003107
Guido van Rossum9722ad81995-09-22 23:49:28 +00003108#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003109
3110/*
Guido van Rossumec22c921996-02-25 04:50:29 +00003111** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003112*/
3113
Guido van Rossum9722ad81995-09-22 23:49:28 +00003114void
3115panic(char * format, ...)
3116{
Barry Warsawfa701a81997-01-16 00:15:11 +00003117 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003118
Barry Warsawfa701a81997-01-16 00:15:11 +00003119 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003120
Guido van Rossum227cf761998-08-05 13:53:32 +00003121 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00003122 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003123
Barry Warsawfa701a81997-01-16 00:15:11 +00003124 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003125
Barry Warsawfa701a81997-01-16 00:15:11 +00003126 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00003127}
Jack Jansen40b546d1995-11-14 10:34:45 +00003128
Guido van Rossumec22c921996-02-25 04:50:29 +00003129/*
3130** Pass events to SIOUX before passing them to Tk.
3131*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003132
Guido van Rossumec22c921996-02-25 04:50:29 +00003133static int
Fred Drake509d79a2000-07-08 04:04:38 +00003134PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003135{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003136 WindowPtr frontwin;
3137 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00003138 ** Sioux eats too many events, so we don't pass it everything. We
3139 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003140 ** the Sioux window is frontmost. This means that Tk menus don't work
3141 ** in that case, but at least we can scroll the sioux window.
3142 ** Note that the SIOUXIsAppWindow() routine we use here is not really
3143 ** part of the external interface of Sioux...
3144 */
3145 frontwin = FrontWindow();
3146 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
3147 if (SIOUXHandleOneEvent(eventPtr))
3148 return 0; /* Nothing happened to the Tcl event queue */
3149 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003150 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003151}
3152
Guido van Rossumec22c921996-02-25 04:50:29 +00003153#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003154
3155/*
3156** Additional Mac specific code for dealing with shared libraries.
3157*/
3158
3159#include <Resources.h>
3160#include <CodeFragments.h>
3161
3162static int loaded_from_shlib = 0;
3163static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003164
Jack Jansen34cc5c31995-10-31 16:15:12 +00003165/*
3166** If this module is dynamically loaded the following routine should
3167** be the init routine. It takes care of adding the shared library to
3168** the resource-file chain, so that the tk routines can find their
3169** resources.
3170*/
3171OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003172init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003173{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00003174 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00003175 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003176 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003177 library_fss = *data->fragLocator.u.onDisk.fileSpec;
3178 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003179 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003180 library_fss = *data->fragLocator.u.inSegs.fileSpec;
3181 loaded_from_shlib = 1;
3182 }
3183 return noErr;
3184}
3185
3186/*
3187** Insert the library resources into the search path. Put them after
3188** the resources from the application. Again, we ignore errors.
3189*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003190static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003191mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003192{
3193 if ( !loaded_from_shlib )
3194 return;
3195 (void)FSpOpenResFile(&library_fss, fsRdPerm);
3196}
3197
Guido van Rossumec22c921996-02-25 04:50:29 +00003198#endif /* GENERATINGCFM */
3199#endif /* macintosh */