blob: 813d27c793e6b9501821552692774275f0b93033 [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öwis71e25a02002-10-01 18:08:06 +000049/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
50 making _tkinter correct for this API means to break earlier
51 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
52 earlier versions. Once Tcl releases before 8.4 don't need to be supported
53 anymore, this should go. */
54#define USE_COMPAT_CONST
55
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000056/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
57 it always; if Tcl is not threaded, the thread functions in
58 Tcl are empty. */
59#define TCL_THREADS
60
Jack Jansencb852442001-12-09 23:15:56 +000061#ifdef TK_FRAMEWORK
62#include <Tcl/tcl.h>
63#include <Tk/tk.h>
64#else
Guido van Rossum18468821994-06-20 07:49:28 +000065#include <tcl.h>
66#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000067#endif
Guido van Rossum18468821994-06-20 07:49:28 +000068
Jason Tishlerbbe89612002-12-31 20:30:46 +000069/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000070#ifndef CONST84_RETURN
71#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000072#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000073#define CONST
74#endif
75
Guido van Rossum3e819a71997-08-01 19:29:02 +000076#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
77
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000078#if TKMAJORMINOR < 8002
79#error "Tk older than 8.2 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000080#endif
81
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000082/* Unicode conversion assumes that Tcl_UniChar is two bytes.
83 We cannot test this directly, so we test UTF-8 size instead,
84 expecting that TCL_UTF_MAX is changed if Tcl ever supports
85 either UTF-16 or UCS-4. */
86#if TCL_UTF_MAX != 3
87#error "unsupported Tcl configuration"
88#endif
89
Guido van Rossuma80649b2000-03-28 20:07:05 +000090#if defined(macintosh)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000091/* Sigh, we have to include this to get at the tcl qd pointer */
92#include <tkMac.h>
Guido van Rossum2ea1c941998-04-28 16:12:43 +000093/* And this one we need to clear the menu bar */
94#include <Menus.h>
Guido van Rossum0d2390c1997-08-14 19:57:07 +000095#endif
96
Jack Jansen84c10b12001-07-16 19:32:52 +000097#if !(defined(MS_WINDOWS) || defined(__CYGWIN__) || defined(macintosh))
98/* Mac has it, but it doesn't really work:-( */
Guido van Rossum0d2390c1997-08-14 19:57:07 +000099#define HAVE_CREATEFILEHANDLER
100#endif
101
Guido van Rossum00d93061998-05-28 23:06:38 +0000102#ifdef HAVE_CREATEFILEHANDLER
103
104/* Tcl_CreateFileHandler() changed several times; these macros deal with the
105 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
106 Unix, only because Jack added it back); when available on Windows, it only
107 applies to sockets. */
108
Guido van Rossum7bf15641998-05-22 18:28:17 +0000109#ifdef MS_WINDOWS
110#define FHANDLETYPE TCL_WIN_SOCKET
111#else
112#define FHANDLETYPE TCL_UNIX_FD
113#endif
114
Guido van Rossum00d93061998-05-28 23:06:38 +0000115/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
116 which uses this to handle Tcl events while the user is typing commands. */
117
118#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000119#define WAIT_FOR_STDIN
120#endif
121
Guido van Rossum00d93061998-05-28 23:06:38 +0000122#endif /* HAVE_CREATEFILEHANDLER */
123
Guido van Rossumad4db171998-06-13 13:56:28 +0000124#ifdef MS_WINDOWS
125#include <conio.h>
126#define WAIT_FOR_STDIN
127#endif
128
Guido van Rossum00d93061998-05-28 23:06:38 +0000129#ifdef WITH_THREAD
130
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000131/* The threading situation is complicated. Tcl is not thread-safe, except
132 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000133 So we need to use a lock around all uses of Tcl. Previously, the Python
134 interpreter lock was used for this. However, this causes problems when
135 other Python threads need to run while Tcl is blocked waiting for events.
136
137 To solve this problem, a separate lock for Tcl is introduced. Holding it
138 is incompatible with holding Python's interpreter lock. The following four
139 macros manipulate both locks together.
140
141 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
142 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
143 that could call an event handler, or otherwise affect the state of a Tcl
144 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000145 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000146 released and the lock for Tcl has been acquired.
147
Guido van Rossum5e977831998-06-15 14:03:52 +0000148 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
149 (For example, when transferring data from the Tcl interpreter result to a
150 Python string object.) This can be done by using different macros to close
151 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
152 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
153 releases the Tcl lock.
154
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000155 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000156 handlers when the handler needs to use Python. Such event handlers are
157 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000158 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000159 the Python interpreter lock, restoring the appropriate thread state, and
160 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
161 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000162 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000163
164 These locks expand to several statements and brackets; they should not be
165 used in branches of if statements and the like.
166
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000167 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
168 only valid in the thread that created it, and all Tk activity must happen in this
169 thread, also. That means that the mainloop must be invoked in the thread that
170 created the interpreter. Invoking commands from other threads is possible;
171 _tkinter will queue an event for the interpreter thread, which will then
172 execute the command and pass back the result. If the main thread is not in the
173 mainloop, and invoking commands causes an exception; if the main loop is running
174 but not processing events, the command invocation will block.
175
176 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
177 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
178 threads. So we use the Tcl TLS API.
179
Guido van Rossum00d93061998-05-28 23:06:38 +0000180*/
181
Guido van Rossum65d5b571998-12-21 19:32:43 +0000182static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000183
184#ifdef TCL_THREADS
185static Tcl_ThreadDataKey state_key;
186typedef PyThreadState *ThreadSpecificData;
187#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
188#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000189static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000190#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000191
192#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000193 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000194 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000195
196#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000197 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000198
Guido van Rossum62320c91998-06-15 04:36:09 +0000199#define ENTER_OVERLAP \
200 Py_END_ALLOW_THREADS
201
202#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000203 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000204
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000205#define ENTER_PYTHON \
206 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000207 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000208
209#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000210 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000211 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
212
213#define CHECK_TCL_APPARTMENT \
214 if (((TkappObject *)self)->threaded && \
215 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
216 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
217 return 0; \
218 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000219
220#else
221
222#define ENTER_TCL
223#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000224#define ENTER_OVERLAP
225#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000226#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000227#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000228#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000229
230#endif
231
Guido van Rossumec22c921996-02-25 04:50:29 +0000232#ifdef macintosh
233
234/*
235** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000236** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000237*/
238
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000239/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000240#define FREECAST (char *)
241
Guido van Rossumec22c921996-02-25 04:50:29 +0000242#include <Events.h> /* For EventRecord */
243
Fred Drake509d79a2000-07-08 04:04:38 +0000244typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
Guido van Rossum2834b972000-10-06 16:58:26 +0000245void Tcl_MacSetEventProc(TclMacConvertEventPtr procPtr);
246int TkMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000247
Jeremy Hylton938ace62002-07-17 16:30:39 +0000248static int PyMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000249
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000250#include <SIOUX.h>
251extern int SIOUXIsAppWindow(WindowPtr);
252
Guido van Rossumec22c921996-02-25 04:50:29 +0000253#endif /* macintosh */
254
Guido van Rossum97867b21996-08-08 19:09:53 +0000255#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000256#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000257#endif
258
Guido van Rossum18468821994-06-20 07:49:28 +0000259/**** Tkapp Object Declaration ****/
260
Jeremy Hylton938ace62002-07-17 16:30:39 +0000261static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000262
Guido van Rossum00d93061998-05-28 23:06:38 +0000263typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000264 PyObject_HEAD
265 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000266 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000267 int threaded; /* True if tcl_platform[threaded] */
268 Tcl_ThreadId thread_id;
269 int dispatching;
270 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000271 So we cache interesting types here. */
272 Tcl_ObjType *BooleanType;
273 Tcl_ObjType *ByteArrayType;
274 Tcl_ObjType *DoubleType;
275 Tcl_ObjType *IntType;
276 Tcl_ObjType *ListType;
277 Tcl_ObjType *ProcBodyType;
278 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000279} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000280
281#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000282#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000283#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000284
Guido van Rossum35d43371997-08-02 00:09:09 +0000285#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000286(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000287
Barry Warsawfa701a81997-01-16 00:15:11 +0000288
289
Guido van Rossum18468821994-06-20 07:49:28 +0000290/**** Error Handling ****/
291
292static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000293static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000294static int errorInCmd = 0;
295static PyObject *excInCmd;
296static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000297static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000298
Barry Warsawfa701a81997-01-16 00:15:11 +0000299
300
Guido van Rossum18468821994-06-20 07:49:28 +0000301static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000302Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000303{
Barry Warsawfa701a81997-01-16 00:15:11 +0000304 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
305 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000306}
307
Barry Warsawfa701a81997-01-16 00:15:11 +0000308
Barry Warsawfa701a81997-01-16 00:15:11 +0000309
Guido van Rossum18468821994-06-20 07:49:28 +0000310/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000311
312#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000313#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000314
Guido van Rossum00d93061998-05-28 23:06:38 +0000315/* Millisecond sleep() for Unix platforms. */
316
317static void
Fred Drake509d79a2000-07-08 04:04:38 +0000318Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000319{
320 /* XXX Too bad if you don't have select(). */
321 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000322 t.tv_sec = milli/1000;
323 t.tv_usec = (milli%1000) * 1000;
324 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
325}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000326#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000327#endif /* WITH_THREAD */
328
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000329/* Wait up to 1s for the mainloop to come up. */
330
331static int
332WaitForMainloop(TkappObject* self)
333{
334 int i;
335 for (i = 0; i < 10; i++) {
336 if (self->dispatching)
337 return 1;
338 Py_BEGIN_ALLOW_THREADS
339 Sleep(100);
340 Py_END_ALLOW_THREADS
341 }
342 if (self->dispatching)
343 return 1;
344 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
345 return 0;
346}
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000347
Guido van Rossum00d93061998-05-28 23:06:38 +0000348
Guido van Rossum18468821994-06-20 07:49:28 +0000349static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000350AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000351{
Guido van Rossum35d43371997-08-02 00:09:09 +0000352 if (PyString_Check(value))
353 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000354#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000355 else if (PyUnicode_Check(value)) {
356 PyObject *v = PyUnicode_AsUTF8String(value);
357 if (v == NULL)
358 return NULL;
359 if (PyList_Append(tmp, v) != 0) {
360 Py_DECREF(v);
361 return NULL;
362 }
363 Py_DECREF(v);
364 return PyString_AsString(v);
365 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000366#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000367 else {
368 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000369 if (v == NULL)
370 return NULL;
371 if (PyList_Append(tmp, v) != 0) {
372 Py_DECREF(v);
373 return NULL;
374 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000375 Py_DECREF(v);
376 return PyString_AsString(v);
377 }
Guido van Rossum18468821994-06-20 07:49:28 +0000378}
379
Barry Warsawfa701a81997-01-16 00:15:11 +0000380
381
Guido van Rossum18468821994-06-20 07:49:28 +0000382#define ARGSZ 64
383
384static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000385Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000386{
Barry Warsawfa701a81997-01-16 00:15:11 +0000387 PyObject *tmp = NULL;
388 char *argvStore[ARGSZ];
389 char **argv = NULL;
390 int fvStore[ARGSZ];
391 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000392 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000393 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000394
Barry Warsawfa701a81997-01-16 00:15:11 +0000395 if (!(tmp = PyList_New(0)))
396 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000397
Barry Warsawfa701a81997-01-16 00:15:11 +0000398 argv = argvStore;
399 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000400
Barry Warsawfa701a81997-01-16 00:15:11 +0000401 if (args == NULL)
402 argc = 0;
403
404 else if (!PyTuple_Check(args)) {
405 argc = 1;
406 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000407 if (!(argv[0] = AsString(args, tmp)))
408 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000409 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000410 else {
411 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000412
Barry Warsawfa701a81997-01-16 00:15:11 +0000413 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000414 argv = (char **)ckalloc(argc * sizeof(char *));
415 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000416 if (argv == NULL || fv == NULL) {
417 PyErr_NoMemory();
418 goto finally;
419 }
420 }
421
422 for (i = 0; i < argc; i++) {
423 PyObject *v = PyTuple_GetItem(args, i);
424 if (PyTuple_Check(v)) {
425 fv[i] = 1;
426 if (!(argv[i] = Merge(v)))
427 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000428 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000429 }
430 else if (v == Py_None) {
431 argc = i;
432 break;
433 }
434 else {
435 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000436 if (!(argv[i] = AsString(v, tmp)))
437 goto finally;
438 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000439 }
440 }
Guido van Rossum18468821994-06-20 07:49:28 +0000441 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000442 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000443 if (res == NULL)
444 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000445
Barry Warsawfa701a81997-01-16 00:15:11 +0000446 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000447 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000448 if (fv[i]) {
449 ckfree(argv[i]);
450 }
451 if (argv != argvStore)
452 ckfree(FREECAST argv);
453 if (fv != fvStore)
454 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000455
Barry Warsawfa701a81997-01-16 00:15:11 +0000456 Py_DECREF(tmp);
457 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000458}
459
Barry Warsawfa701a81997-01-16 00:15:11 +0000460
461
Guido van Rossum18468821994-06-20 07:49:28 +0000462static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000463Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000464{
Barry Warsawfa701a81997-01-16 00:15:11 +0000465 int argc;
466 char **argv;
467 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000468
Barry Warsawfa701a81997-01-16 00:15:11 +0000469 if (list == NULL) {
470 Py_INCREF(Py_None);
471 return Py_None;
472 }
Guido van Rossum18468821994-06-20 07:49:28 +0000473
Guido van Rossum00d93061998-05-28 23:06:38 +0000474 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000475 /* Not a list.
476 * Could be a quoted string containing funnies, e.g. {"}.
477 * Return the string itself.
478 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000479 return PyString_FromString(list);
480 }
Guido van Rossum18468821994-06-20 07:49:28 +0000481
Barry Warsawfa701a81997-01-16 00:15:11 +0000482 if (argc == 0)
483 v = PyString_FromString("");
484 else if (argc == 1)
485 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000486 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000487 int i;
488 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000489
Barry Warsawfa701a81997-01-16 00:15:11 +0000490 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000491 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000492 Py_DECREF(v);
493 v = NULL;
494 break;
495 }
496 PyTuple_SetItem(v, i, w);
497 }
498 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000499 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000500 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000501}
502
Martin v. Löwisffad6332002-11-26 09:28:05 +0000503/* In some cases, Tcl will still return strings that are supposed to be
504 lists. SplitObj walks through a nested tuple, finding string objects that
505 need to be split. */
506
507PyObject *
508SplitObj(PyObject *arg)
509{
510 if (PyTuple_Check(arg)) {
511 int i, size;
512 PyObject *elem, *newelem, *result;
513
514 size = PyTuple_Size(arg);
515 result = NULL;
516 /* Recursively invoke SplitObj for all tuple items.
517 If this does not return a new object, no action is
518 needed. */
519 for(i = 0; i < size; i++) {
520 elem = PyTuple_GetItem(arg, i);
521 newelem = SplitObj(elem);
522 if (!newelem) {
523 Py_XDECREF(result);
524 return NULL;
525 }
526 if (!result) {
527 int k;
528 if (newelem == elem) {
529 Py_DECREF(newelem);
530 continue;
531 }
532 result = PyTuple_New(size);
533 if (!result)
534 return NULL;
535 for(k = 0; k < i; k++) {
536 elem = PyTuple_GetItem(arg, k);
537 Py_INCREF(elem);
538 PyTuple_SetItem(result, k, elem);
539 }
540 }
541 PyTuple_SetItem(result, i, newelem);
542 }
543 if (result)
544 return result;
545 /* Fall through, returning arg. */
546 }
547 else if (PyString_Check(arg)) {
548 int argc;
549 char **argv;
550 char *list = PyString_AsString(arg);
551
552 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
553 Py_INCREF(arg);
554 return arg;
555 }
556 Tcl_Free(FREECAST argv);
557 if (argc > 1)
558 return Split(PyString_AsString(arg));
559 /* Fall through, returning arg. */
560 }
561 Py_INCREF(arg);
562 return arg;
563}
Barry Warsawfa701a81997-01-16 00:15:11 +0000564
565
Guido van Rossum18468821994-06-20 07:49:28 +0000566/**** Tkapp Object ****/
567
568#ifndef WITH_APPINIT
569int
Fred Drake509d79a2000-07-08 04:04:38 +0000570Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000571{
Barry Warsawfa701a81997-01-16 00:15:11 +0000572 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000573
Barry Warsawfa701a81997-01-16 00:15:11 +0000574 main = Tk_MainWindow(interp);
575 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000576 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000577 return TCL_ERROR;
578 }
579 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000580 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000581 return TCL_ERROR;
582 }
583 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000584}
585#endif /* !WITH_APPINIT */
586
Guido van Rossum18468821994-06-20 07:49:28 +0000587
Barry Warsawfa701a81997-01-16 00:15:11 +0000588
589
590/* Initialize the Tk application; see the `main' function in
591 * `tkMain.c'.
592 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000593
Thomas Wouters58d05102000-07-24 14:43:35 +0000594static void EnableEventHook(void); /* Forward */
595static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000596
Barry Warsawfa701a81997-01-16 00:15:11 +0000597static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000598Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000599 int interactive, int wantobjects)
Barry Warsawfa701a81997-01-16 00:15:11 +0000600{
601 TkappObject *v;
602 char *argv0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000603
Guido van Rossumb18618d2000-05-03 23:44:39 +0000604 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000605 if (v == NULL)
606 return NULL;
607
608 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000609 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000610 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
611 TCL_GLOBAL_ONLY) != NULL;
612 v->thread_id = Tcl_GetCurrentThread();
613 v->dispatching = 0;
614
615#ifndef TCL_THREADS
616 if (v->threaded) {
617 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
618 Py_DECREF(v);
619 return 0;
620 }
621#endif
622 if (v->threaded && tcl_lock) {
623 /* If Tcl is threaded, we don't need the lock. */
624 PyThread_free_lock(tcl_lock);
625 tcl_lock = NULL;
626 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000627
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000628 v->BooleanType = Tcl_GetObjType("boolean");
629 v->ByteArrayType = Tcl_GetObjType("bytearray");
630 v->DoubleType = Tcl_GetObjType("double");
631 v->IntType = Tcl_GetObjType("int");
632 v->ListType = Tcl_GetObjType("list");
633 v->ProcBodyType = Tcl_GetObjType("procbody");
634 v->StringType = Tcl_GetObjType("string");
635
Guido van Rossuma80649b2000-03-28 20:07:05 +0000636#if defined(macintosh)
637 /* This seems to be needed */
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000638 ClearMenuBar();
639 TkMacInitMenus(v->interp);
640#endif
Jack Jansencb852442001-12-09 23:15:56 +0000641
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000642 /* Delete the 'exit' command, which can screw things up */
643 Tcl_DeleteCommand(v->interp, "exit");
644
Barry Warsawfa701a81997-01-16 00:15:11 +0000645 if (screenName != NULL)
646 Tcl_SetVar2(v->interp, "env", "DISPLAY",
647 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000648
Barry Warsawfa701a81997-01-16 00:15:11 +0000649 if (interactive)
650 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
651 else
652 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000653
Barry Warsawfa701a81997-01-16 00:15:11 +0000654 /* This is used to get the application class for Tk 4.1 and up */
655 argv0 = (char*)ckalloc(strlen(className) + 1);
656 if (!argv0) {
657 PyErr_NoMemory();
658 Py_DECREF(v);
659 return NULL;
660 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000661
Barry Warsawfa701a81997-01-16 00:15:11 +0000662 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000663 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000664 argv0[0] = tolower(argv0[0]);
665 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
666 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000667
Barry Warsawfa701a81997-01-16 00:15:11 +0000668 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000669 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000670
Guido van Rossum7bf15641998-05-22 18:28:17 +0000671 EnableEventHook();
672
Barry Warsawfa701a81997-01-16 00:15:11 +0000673 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000674}
675
Barry Warsawfa701a81997-01-16 00:15:11 +0000676
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000677static void
678Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
679 Tcl_Condition *cond, Tcl_Mutex *mutex)
680{
681 Py_BEGIN_ALLOW_THREADS;
682 Tcl_MutexLock(mutex);
683 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
684 Tcl_ThreadAlert(self->thread_id);
685 Tcl_ConditionWait(cond, mutex, NULL);
686 Tcl_MutexUnlock(mutex);
687 Py_END_ALLOW_THREADS
688}
689
Barry Warsawfa701a81997-01-16 00:15:11 +0000690
Guido van Rossum18468821994-06-20 07:49:28 +0000691/** Tcl Eval **/
692
Martin v. Löwisffad6332002-11-26 09:28:05 +0000693typedef struct {
694 PyObject_HEAD
695 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000696 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000697} PyTclObject;
698
699staticforward PyTypeObject PyTclObject_Type;
700#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
701
702static PyObject *
703newPyTclObject(Tcl_Obj *arg)
704{
705 PyTclObject *self;
706 self = PyObject_New(PyTclObject, &PyTclObject_Type);
707 if (self == NULL)
708 return NULL;
709 Tcl_IncrRefCount(arg);
710 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000711 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000712 return (PyObject*)self;
713}
714
715static void
716PyTclObject_dealloc(PyTclObject *self)
717{
718 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000719 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000720 PyObject_Del(self);
721}
722
723static PyObject *
724PyTclObject_str(PyTclObject *self)
725{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000726 if (self->string && PyString_Check(self->string)) {
727 Py_INCREF(self->string);
728 return self->string;
729 }
730 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000731 return PyString_FromString(Tcl_GetString(self->value));
732}
733
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000734/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000735PyDoc_STRVAR(PyTclObject_string__doc__,
736"the string representation of this object, either as string or Unicode");
737
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000738static PyObject *
739PyTclObject_string(PyTclObject *self, void *ignored)
740{
741 char *s;
742 int i, len;
743 if (!self->string) {
744 s = Tcl_GetStringFromObj(self->value, &len);
745 for (i = 0; i < len; i++)
746 if (s[i] & 0x80)
747 break;
748#ifdef Py_USING_UNICODE
749 if (i == len)
750 /* It is an ASCII string. */
751 self->string = PyString_FromStringAndSize(s, len);
752 else {
753 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
754 if (!self->string) {
755 PyErr_Clear();
756 self->string = PyString_FromStringAndSize(s, len);
757 }
758 }
759#else
760 self->string = PyString_FromStringAndSize(s, len);
761#endif
762 if (!self->string)
763 return NULL;
764 }
765 Py_INCREF(self->string);
766 return self->string;
767}
768
769#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000770PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
771
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000772static PyObject *
773PyTclObject_unicode(PyTclObject *self, void *ignored)
774{
775 char *s;
776 int len;
777 if (self->string && PyUnicode_Check(self->string)) {
778 Py_INCREF(self->string);
779 return self->string;
780 }
781 /* XXX Could chache result if it is non-ASCII. */
782 s = Tcl_GetStringFromObj(self->value, &len);
783 return PyUnicode_DecodeUTF8(s, len, "strict");
784}
785#endif
786
Martin v. Löwisffad6332002-11-26 09:28:05 +0000787static PyObject *
788PyTclObject_repr(PyTclObject *self)
789{
790 char buf[50];
791 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
792 self->value->typePtr->name, (int)self->value);
793 return PyString_FromString(buf);
794}
795
Martin v. Löwis39195712003-01-04 00:33:13 +0000796PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
797
Martin v. Löwisffad6332002-11-26 09:28:05 +0000798static PyObject*
799get_typename(PyTclObject* obj, void* ignored)
800{
801 return PyString_FromString(obj->value->typePtr->name);
802}
803
Martin v. Löwis39195712003-01-04 00:33:13 +0000804
Martin v. Löwisffad6332002-11-26 09:28:05 +0000805static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000806 {"typename", (getter)get_typename, NULL, get_typename__doc__},
807 {"string", (getter)PyTclObject_string, NULL,
808 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000809 {0},
810};
811
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000812static PyMethodDef PyTclObject_methods[] = {
813 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000814 PyTclObject_unicode__doc__},
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000815 {0}
816};
817
Martin v. Löwisffad6332002-11-26 09:28:05 +0000818statichere PyTypeObject PyTclObject_Type = {
819 PyObject_HEAD_INIT(NULL)
820 0, /*ob_size*/
821 "_tkinter.Tcl_Obj", /*tp_name*/
822 sizeof(PyTclObject), /*tp_basicsize*/
823 0, /*tp_itemsize*/
824 /* methods */
825 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
826 0, /*tp_print*/
827 0, /*tp_getattr*/
828 0, /*tp_setattr*/
829 0, /*tp_compare*/
830 (reprfunc)PyTclObject_repr, /*tp_repr*/
831 0, /*tp_as_number*/
832 0, /*tp_as_sequence*/
833 0, /*tp_as_mapping*/
834 0, /*tp_hash*/
835 0, /*tp_call*/
836 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000837 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000838 0, /*tp_setattro*/
839 0, /*tp_as_buffer*/
840 Py_TPFLAGS_DEFAULT, /*tp_flags*/
841 0, /*tp_doc*/
842 0, /*tp_traverse*/
843 0, /*tp_clear*/
844 0, /*tp_richcompare*/
845 0, /*tp_weaklistoffset*/
846 0, /*tp_iter*/
847 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000848 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000849 0, /*tp_members*/
850 PyTclObject_getsetlist, /*tp_getset*/
851 0, /*tp_base*/
852 0, /*tp_dict*/
853 0, /*tp_descr_get*/
854 0, /*tp_descr_set*/
855 0, /*tp_dictoffset*/
856 0, /*tp_init*/
857 0, /*tp_alloc*/
858 0, /*tp_new*/
859 0, /*tp_free*/
860 0, /*tp_is_gc*/
861};
862
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000863static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000864AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000865{
866 Tcl_Obj *result;
867
868 if (PyString_Check(value))
869 return Tcl_NewStringObj(PyString_AS_STRING(value),
870 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000871 else if (PyBool_Check(value))
872 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000873 else if (PyInt_Check(value))
874 return Tcl_NewLongObj(PyInt_AS_LONG(value));
875 else if (PyFloat_Check(value))
876 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
877 else if (PyTuple_Check(value)) {
878 Tcl_Obj **argv = (Tcl_Obj**)
879 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
880 int i;
881 if(!argv)
882 return 0;
883 for(i=0;i<PyTuple_Size(value);i++)
884 argv[i] = AsObj(PyTuple_GetItem(value,i));
885 result = Tcl_NewListObj(PyTuple_Size(value), argv);
886 ckfree(FREECAST argv);
887 return result;
888 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000889#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000890 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000891 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
892 int size = PyUnicode_GET_SIZE(value);
893 /* This #ifdef assumes that Tcl uses UCS-2.
894 See TCL_UTF_MAX test above. */
895#ifdef Py_UNICODE_WIDE
896 Tcl_UniChar *outbuf;
897 int i;
898 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
899 if (!outbuf) {
900 PyErr_NoMemory();
901 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000902 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000903 for (i = 0; i < size; i++) {
904 if (inbuf[i] >= 0x10000) {
905 /* Tcl doesn't do UTF-16, yet. */
906 PyErr_SetString(PyExc_ValueError,
907 "unsupported character");
908 ckfree(FREECAST outbuf);
909 return NULL;
910 }
911 outbuf[i] = inbuf[i];
912 }
913 result = Tcl_NewUnicodeObj(outbuf, size);
914 ckfree(FREECAST outbuf);
915 return result;
916#else
917 return Tcl_NewUnicodeObj(inbuf, size);
918#endif
919
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000920 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000921#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000922 else if(PyTclObject_Check(value)) {
923 Tcl_Obj *v = ((PyTclObject*)value)->value;
924 Tcl_IncrRefCount(v);
925 return v;
926 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000927 else {
928 PyObject *v = PyObject_Str(value);
929 if (!v)
930 return 0;
931 result = AsObj(v);
932 Py_DECREF(v);
933 return result;
934 }
935}
936
Martin v. Löwisffad6332002-11-26 09:28:05 +0000937static PyObject*
938FromObj(PyObject* tkapp, Tcl_Obj *value)
939{
940 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000941 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000942
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000943 if (value->typePtr == NULL) {
944 /* If the result contains any bytes with the top bit set,
945 it's UTF-8 and we should decode it to Unicode */
946#ifdef Py_USING_UNICODE
947 int i;
948 char *s = value->bytes;
949 int len = value->length;
950 for (i = 0; i < len; i++) {
951 if (value->bytes[i] & 0x80)
952 break;
953 }
954
955 if (i == value->length)
956 result = PyString_FromStringAndSize(s, len);
957 else {
958 /* Convert UTF-8 to Unicode string */
959 result = PyUnicode_DecodeUTF8(s, len, "strict");
960 if (result == NULL) {
961 PyErr_Clear();
962 result = PyString_FromStringAndSize(s, len);
963 }
964 }
965#else
966 res = PyString_FromStringAndSize(value->bytes, value->length);
967#endif
968 return result;
969 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000970
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000971 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000972 result = value->internalRep.longValue ? Py_True : Py_False;
973 Py_INCREF(result);
974 return result;
975 }
976
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000977 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000978 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000979 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000980 return PyString_FromStringAndSize(data, size);
981 }
982
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000983 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000984 return PyFloat_FromDouble(value->internalRep.doubleValue);
985 }
986
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000987 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000988 return PyInt_FromLong(value->internalRep.longValue);
989 }
990
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000991 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000992 int size;
993 int i, status;
994 PyObject *elem;
995 Tcl_Obj *tcl_elem;
996
997 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
998 if (status == TCL_ERROR)
999 return Tkinter_Error(tkapp);
1000 result = PyTuple_New(size);
1001 if (!result)
1002 return NULL;
1003 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001004 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001005 value, i, &tcl_elem);
1006 if (status == TCL_ERROR) {
1007 Py_DECREF(result);
1008 return Tkinter_Error(tkapp);
1009 }
1010 elem = FromObj(tkapp, tcl_elem);
1011 if (!elem) {
1012 Py_DECREF(result);
1013 return NULL;
1014 }
1015 PyTuple_SetItem(result, i, elem);
1016 }
1017 return result;
1018 }
1019
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001020 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001021 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001022 }
1023
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001024 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001025#ifdef Py_USING_UNICODE
1026#ifdef Py_UNICODE_WIDE
1027 PyObject *result;
1028 int size;
1029 Tcl_UniChar *input;
1030 Py_UNICODE *output;
1031
1032 size = Tcl_GetCharLength(value);
1033 result = PyUnicode_FromUnicode(NULL, size);
1034 if (!result)
1035 return NULL;
1036 input = Tcl_GetUnicode(value);
1037 output = PyUnicode_AS_UNICODE(result);
1038 while (size--)
1039 *output++ = *input++;
1040 return result;
1041#else
1042 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1043 Tcl_GetCharLength(value));
1044#endif
1045#else
1046 int size;
1047 char *c;
1048 c = Tcl_GetStringFromObj(value, &size);
1049 return PyString_FromStringAndSize(c, size);
1050#endif
1051 }
1052
1053 return newPyTclObject(value);
1054}
1055
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001056/* This mutex synchronizes inter-thread command calls. */
1057
1058TCL_DECLARE_MUTEX(call_mutex)
1059
1060typedef struct Tkapp_CallEvent {
1061 Tcl_Event ev; /* Must be first */
1062 TkappObject *self;
1063 PyObject *args;
1064 int flags;
1065 PyObject **res;
1066 PyObject **exc_type, **exc_value, **exc_tb;
1067 Tcl_Condition done;
1068} Tkapp_CallEvent;
1069
1070void
1071Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001072{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001073 int i;
1074 for (i = 0; i < objc; i++)
1075 Tcl_DecrRefCount(objv[i]);
1076 if (objv != objStore)
1077 ckfree(FREECAST objv);
1078}
Guido van Rossum18468821994-06-20 07:49:28 +00001079
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001080/* Convert Python objects to Tcl objects. This must happen in the
1081 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001082
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001083static Tcl_Obj**
1084Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1085{
1086 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001087 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001088 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001089 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001090
Guido van Rossum212643f1998-04-29 16:22:14 +00001091 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001092 objv[0] = AsObj(args);
1093 if (objv[0] == 0)
1094 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001095 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001096 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001097 }
1098 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001099 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001100
Guido van Rossum632de272000-03-29 00:19:50 +00001101 if (objc > ARGSZ) {
1102 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1103 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001104 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001105 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001106 goto finally;
1107 }
1108 }
1109
Guido van Rossum632de272000-03-29 00:19:50 +00001110 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001111 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001112 if (v == Py_None) {
1113 objc = i;
1114 break;
1115 }
Guido van Rossum632de272000-03-29 00:19:50 +00001116 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001117 if (!objv[i]) {
1118 /* Reset objc, so it attempts to clear
1119 objects only up to i. */
1120 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001121 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001122 }
Guido van Rossum632de272000-03-29 00:19:50 +00001123 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001124 }
1125 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001126 *pobjc = objc;
1127 return objv;
1128finally:
1129 Tkapp_CallDeallocArgs(objv, objStore, objc);
1130 return NULL;
1131}
Guido van Rossum212643f1998-04-29 16:22:14 +00001132
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001133/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001134
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001135static PyObject*
1136Tkapp_CallResult(TkappObject *self)
1137{
1138 PyObject *res = NULL;
1139 if(self->wantobjects) {
1140 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001141 /* Not sure whether the IncrRef is necessary, but something
1142 may overwrite the interpreter result while we are
1143 converting it. */
1144 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001145 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001146 Tcl_DecrRefCount(value);
1147 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001148 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001149 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001150
Guido van Rossum990f5c62000-05-04 15:07:16 +00001151 /* If the result contains any bytes with the top bit set,
1152 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001153#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001154 while (*p != '\0') {
1155 if (*p & 0x80)
1156 break;
1157 p++;
1158 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001159
Guido van Rossum990f5c62000-05-04 15:07:16 +00001160 if (*p == '\0')
1161 res = PyString_FromStringAndSize(s, (int)(p-s));
1162 else {
1163 /* Convert UTF-8 to Unicode string */
1164 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001165 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1166 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001167 PyErr_Clear();
1168 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001169 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001170 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001171#else
1172 p = strchr(p, '\0');
1173 res = PyString_FromStringAndSize(s, (int)(p-s));
1174#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001175 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001176 return res;
1177}
Guido van Rossum632de272000-03-29 00:19:50 +00001178
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001179/* Tkapp_CallProc is the event procedure that is executed in the context of
1180 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1181 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001182
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001183static int
1184Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1185{
1186 Tcl_Obj *objStore[ARGSZ];
1187 Tcl_Obj **objv;
1188 int objc;
1189 int i;
1190 ENTER_PYTHON
1191 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1192 if (!objv) {
1193 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1194 *(e->res) = NULL;
1195 }
1196 LEAVE_PYTHON
1197 if (!objv)
1198 goto done;
1199 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1200 ENTER_PYTHON
1201 if (i == TCL_ERROR) {
1202 *(e->res) = NULL;
1203 *(e->exc_type) = NULL;
1204 *(e->exc_tb) = NULL;
1205 *(e->exc_value) = PyObject_CallFunction(
1206 Tkinter_TclError, "s",
1207 Tcl_GetStringResult(e->self->interp));
1208 }
1209 else {
1210 *(e->res) = Tkapp_CallResult(e->self);
1211 }
1212 LEAVE_PYTHON
1213 done:
1214 /* Wake up calling thread. */
1215 Tcl_MutexLock(&call_mutex);
1216 Tcl_ConditionNotify(&e->done);
1217 Tcl_MutexUnlock(&call_mutex);
1218 return 1;
1219}
1220
1221/* This is the main entry point for calling a Tcl command.
1222 It supports three cases, with regard to threading:
1223 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1224 the context of the calling thread.
1225 2. Tcl is threaded, caller of the command is in the interpreter thread:
1226 Execute the command in the calling thread. Since the Tcl lock will
1227 not be used, we can merge that with case 1.
1228 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1229 the interpreter thread. Allocation of Tcl objects needs to occur in the
1230 interpreter thread, so we ship the PyObject* args to the target thread,
1231 and perform processing there. */
1232
1233static PyObject *
1234Tkapp_Call(PyObject *_self, PyObject *args)
1235{
1236 Tcl_Obj *objStore[ARGSZ];
1237 Tcl_Obj **objv = NULL;
1238 int objc, i;
1239 PyObject *res = NULL;
1240 TkappObject *self = (TkappObject*)_self;
1241 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1242 int flags = TCL_EVAL_DIRECT;
1243
1244 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1245 /* We cannot call the command directly. Instead, we must
1246 marshal the parameters to the interpreter thread. */
1247 Tkapp_CallEvent *ev;
1248 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001249 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001250 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001251 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1252 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1253 ev->self = self;
1254 ev->args = args;
1255 ev->res = &res;
1256 ev->exc_type = &exc_type;
1257 ev->exc_value = &exc_value;
1258 ev->exc_tb = &exc_tb;
1259 ev->done = (Tcl_Condition)0;
1260
1261 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1262
1263 if (res == NULL) {
1264 if (exc_type)
1265 PyErr_Restore(exc_type, exc_value, exc_tb);
1266 else
1267 PyErr_SetObject(Tkinter_TclError, exc_value);
1268 }
1269 }
1270 else {
1271
1272 objv = Tkapp_CallArgs(args, objStore, &objc);
1273 if (!objv)
1274 return NULL;
1275
1276 ENTER_TCL
1277
1278 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1279
1280 ENTER_OVERLAP
1281
1282 if (i == TCL_ERROR)
1283 Tkinter_Error(_self);
1284 else
1285 res = Tkapp_CallResult(self);
1286
1287 LEAVE_OVERLAP_TCL
1288
1289 Tkapp_CallDeallocArgs(objv, objStore, objc);
1290 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001291 return res;
1292}
1293
1294
1295static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001296Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001297{
Guido van Rossum212643f1998-04-29 16:22:14 +00001298 /* Could do the same here as for Tkapp_Call(), but this is not used
1299 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1300 way for the user to do what all its Global* variants do (save and
1301 reset the scope pointer, call the local version, restore the saved
1302 scope pointer). */
1303
Guido van Rossum62320c91998-06-15 04:36:09 +00001304 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001305 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001306
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001307 CHECK_TCL_APPARTMENT;
1308
Guido van Rossum62320c91998-06-15 04:36:09 +00001309 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001310 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001311 int err;
1312 ENTER_TCL
1313 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001314 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001315 if (err == TCL_ERROR)
1316 res = Tkinter_Error(self);
1317 else
1318 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001319 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001320 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001321 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001322
1323 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001324}
1325
1326static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001327Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001328{
Barry Warsawfa701a81997-01-16 00:15:11 +00001329 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001330 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001331 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001332
Guido van Rossum43713e52000-02-29 13:59:29 +00001333 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001334 return NULL;
1335
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001336 CHECK_TCL_APPARTMENT;
1337
Guido van Rossum00d93061998-05-28 23:06:38 +00001338 ENTER_TCL
1339 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001340 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001341 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001342 res = Tkinter_Error(self);
1343 else
1344 res = PyString_FromString(Tkapp_Result(self));
1345 LEAVE_OVERLAP_TCL
1346 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001347}
1348
1349static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001350Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001351{
Barry Warsawfa701a81997-01-16 00:15:11 +00001352 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001353 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001354 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001355
Guido van Rossum43713e52000-02-29 13:59:29 +00001356 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001357 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001358
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001359 CHECK_TCL_APPARTMENT;
1360
Guido van Rossum00d93061998-05-28 23:06:38 +00001361 ENTER_TCL
1362 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001363 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001364 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001365 res = Tkinter_Error(self);
1366 else
1367 res = PyString_FromString(Tkapp_Result(self));
1368 LEAVE_OVERLAP_TCL
1369 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001370}
1371
1372static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001373Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001374{
Barry Warsawfa701a81997-01-16 00:15:11 +00001375 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001376 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001377 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001378
Guido van Rossum43713e52000-02-29 13:59:29 +00001379 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001380 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001381
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001382 CHECK_TCL_APPARTMENT;
1383
Guido van Rossum00d93061998-05-28 23:06:38 +00001384 ENTER_TCL
1385 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001386 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001387 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001388 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001389
Guido van Rossum62320c91998-06-15 04:36:09 +00001390 else
1391 res = PyString_FromString(Tkapp_Result(self));
1392 LEAVE_OVERLAP_TCL
1393 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001394}
1395
1396static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001397Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001398{
Barry Warsawfa701a81997-01-16 00:15:11 +00001399 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001400 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001401 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001402
Guido van Rossum35d43371997-08-02 00:09:09 +00001403 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001404 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001405
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001406 CHECK_TCL_APPARTMENT;
1407
Guido van Rossum00d93061998-05-28 23:06:38 +00001408 ENTER_TCL
1409 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001410 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001411 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001412 res = Tkinter_Error(self);
1413 else
1414 res = PyString_FromString(Tkapp_Result(self));
1415 LEAVE_OVERLAP_TCL
1416 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001417}
1418
1419static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001420Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001421{
Barry Warsawfa701a81997-01-16 00:15:11 +00001422 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001423
Guido van Rossum43713e52000-02-29 13:59:29 +00001424 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001425 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001426 CHECK_TCL_APPARTMENT;
1427
Guido van Rossum00d93061998-05-28 23:06:38 +00001428 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001429 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001430 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001431
Barry Warsawfa701a81997-01-16 00:15:11 +00001432 Py_INCREF(Py_None);
1433 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001434}
1435
Barry Warsawfa701a81997-01-16 00:15:11 +00001436
1437
Guido van Rossum18468821994-06-20 07:49:28 +00001438/** Tcl Variable **/
1439
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001440TCL_DECLARE_MUTEX(var_mutex)
1441
Martin v. Löwis5b177f12002-12-30 18:14:15 +00001442typedef CONST84_RETURN char* (*EventFunc1)(Tcl_Interp*, CONST char*, int);
1443typedef CONST84_RETURN char* (*EventFunc2)(Tcl_Interp*, CONST char*, CONST char*, int);
1444typedef CONST84_RETURN char* (*EventFunc3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001445typedef struct VarEvent {
1446 Tcl_Event ev; /* must be first */
1447 TkappObject *self;
1448 char* arg1;
1449 char* arg2;
1450 char* arg3;
1451 int flags;
1452 EventFunc1 func1;
1453 EventFunc2 func2;
1454 EventFunc3 func3;
1455 PyObject **res;
1456 PyObject **exc;
1457 Tcl_Condition cond;
1458 int coderesult;
1459} VarEvent;
1460
1461static const char*
1462var_perform(VarEvent *ev)
1463{
1464 if (!ev->arg2 && !ev->arg2)
1465 return ev->func1(ev->self->interp, ev->arg1, ev->flags);
1466 if (!ev->arg3)
1467 return ev->func2(ev->self->interp, ev->arg1,
1468 ev->arg2, ev->flags);
1469 return ev->func3(ev->self->interp, ev->arg1, ev->arg2,
1470 ev->arg3, ev->flags);
1471}
1472
1473static void
1474var_fill_result(VarEvent *ev, const char* res)
1475{
1476 if (ev->coderesult) {
1477 if ((int)res != TCL_ERROR) {
1478 Py_INCREF(Py_None);
1479 *(ev->res) = Py_None;
1480 return;
1481 }
1482 }
1483 else if (res) {
1484 *(ev->res) = PyString_FromString(res);
1485 return;
1486 }
1487
1488 *(ev->res) = NULL;
1489 *(ev->exc) = PyObject_CallFunction(
1490 Tkinter_TclError, "s",
1491 Tcl_GetStringResult(ev->self->interp));
1492
1493}
1494
1495static int
1496var_proc(VarEvent* ev, int flags)
1497{
1498 const char *result = var_perform(ev);
1499 ENTER_PYTHON
1500 var_fill_result(ev, result);
1501 Tcl_MutexLock(&var_mutex);
1502 Tcl_ConditionNotify(&ev->cond);
1503 Tcl_MutexUnlock(&var_mutex);
1504 LEAVE_PYTHON
1505 return 1;
1506}
1507
1508static PyObject*
1509var_invoke(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
1510 EventFunc1 func1, EventFunc2 func2, EventFunc3 func3,
1511 int coderesult)
1512{
1513 VarEvent _ev;
1514 TkappObject *self = (TkappObject*)_self;
1515 VarEvent *ev = self->threaded ?
1516 (VarEvent*)ckalloc(sizeof(VarEvent)) : &_ev;
1517 PyObject *res, *exc;
1518
1519 ev->self = self;
1520 ev->arg1 = arg1;
1521 ev->arg2 = arg2;
1522 ev->arg3 = arg3;
1523 ev->flags = flags;
1524 ev->func1 = func1;
1525 ev->func2 = func2;
1526 ev->func3 = func3;
1527 ev->coderesult = coderesult;
1528 ev->res = &res;
1529 ev->exc = &exc;
1530 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1531 /* The current thread is not the interpreter thread. Marshal
1532 the call to the interpreter thread, then wait for
1533 completion. */
1534
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001535 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001537 ev->cond = NULL;
1538 ev->ev.proc = (Tcl_EventProc*)var_proc;
1539 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1540 }
1541 else {
1542 /* Tcl is not threaded, or this is the interpreter thread. To
1543 perform the call, we must hold the TCL lock. To receive the
1544 results, we must also hold the Python lock. */
1545 const char *result;
1546 ENTER_TCL
1547 result = var_perform(ev);
1548 ENTER_OVERLAP
1549 var_fill_result(ev, result);
1550 LEAVE_OVERLAP_TCL
1551 }
1552 if (!res) {
1553 PyErr_SetObject(Tkinter_TclError, exc);
1554 return NULL;
1555 }
1556 return res;
1557}
1558
1559static PyObject*
1560var_invoke2(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
Martin v. Löwis5b177f12002-12-30 18:14:15 +00001561 int (*func1)(Tcl_Interp*, CONST char*, int),
1562 int (*func2)(Tcl_Interp*, CONST char*, CONST char*, int),
1563 int (*func3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001564{
1565 return var_invoke(_self, arg1, arg2, arg3, flags,
1566 (EventFunc1)func1, (EventFunc2)func2,
1567 (EventFunc3)func3, 1);
1568}
1569
Guido van Rossum18468821994-06-20 07:49:28 +00001570static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001571SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001572{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001573 char *name1, *name2, *s;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001574 PyObject *res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001575 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +00001576 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +00001577
Guido van Rossum62320c91998-06-15 04:36:09 +00001578 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +00001579 if (!tmp)
1580 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001581
Guido van Rossum43713e52000-02-29 13:59:29 +00001582 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001583 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +00001584 s = AsString(newValue, tmp);
Guido van Rossum2834b972000-10-06 16:58:26 +00001585 if (s == NULL)
1586 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001587 res = var_invoke(self, name1, s, NULL, flags,
1588 NULL, Tcl_SetVar, NULL, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001589 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001590 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001591 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001592 if (PyArg_ParseTuple(args, "ssO:setvar",
1593 &name1, &name2, &newValue)) {
1594 s = AsString(newValue, tmp);
1595 if (s == NULL)
1596 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001597 res = var_invoke(self, name1, name2, s, flags,
1598 NULL, NULL, Tcl_SetVar2, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001599 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001600 else {
Guido van Rossum00d93061998-05-28 23:06:38 +00001601 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +00001602 return NULL;
1603 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001604 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001605 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +00001606
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001607 if (!res)
1608 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001609
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001610 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001611 Py_INCREF(Py_None);
1612 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001613}
1614
1615static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001616Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001617{
Barry Warsawfa701a81997-01-16 00:15:11 +00001618 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001619}
1620
1621static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001622Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001623{
Barry Warsawfa701a81997-01-16 00:15:11 +00001624 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001625}
1626
Barry Warsawfa701a81997-01-16 00:15:11 +00001627
1628
Guido van Rossum18468821994-06-20 07:49:28 +00001629static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001630GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001631{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001632 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001633 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001634
Guido van Rossum43713e52000-02-29 13:59:29 +00001635 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001636 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001637
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001638 res = var_invoke(self, name1, name2, NULL, flags,
1639 Tcl_GetVar, Tcl_GetVar2, NULL, 0);
Guido van Rossum62320c91998-06-15 04:36:09 +00001640 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001641}
1642
1643static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001644Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001645{
Barry Warsawfa701a81997-01-16 00:15:11 +00001646 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001647}
1648
1649static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001650Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001651{
Barry Warsawfa701a81997-01-16 00:15:11 +00001652 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001653}
1654
Barry Warsawfa701a81997-01-16 00:15:11 +00001655
1656
Guido van Rossum18468821994-06-20 07:49:28 +00001657static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001658UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001659{
Guido van Rossum35d43371997-08-02 00:09:09 +00001660 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001661 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001662
Guido van Rossum43713e52000-02-29 13:59:29 +00001663 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001664 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001665
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001666 res = var_invoke2(self, name1, name2, NULL, flags,
1667 Tcl_UnsetVar, Tcl_UnsetVar2, NULL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001668 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001669}
1670
1671static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001672Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001673{
Barry Warsawfa701a81997-01-16 00:15:11 +00001674 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001675}
1676
1677static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001678Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001679{
Barry Warsawfa701a81997-01-16 00:15:11 +00001680 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001681}
1682
Barry Warsawfa701a81997-01-16 00:15:11 +00001683
1684
Guido van Rossum18468821994-06-20 07:49:28 +00001685/** Tcl to Python **/
1686
1687static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001688Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001689{
Barry Warsawfa701a81997-01-16 00:15:11 +00001690 char *s;
1691 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001692
Martin v. Löwisffad6332002-11-26 09:28:05 +00001693 if (PyTuple_Size(args) == 1) {
1694 PyObject* o = PyTuple_GetItem(args, 0);
1695 if (PyInt_Check(o)) {
1696 Py_INCREF(o);
1697 return o;
1698 }
1699 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001700 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001701 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001702 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001703 return Tkinter_Error(self);
1704 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001705}
1706
1707static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001708Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001709{
Barry Warsawfa701a81997-01-16 00:15:11 +00001710 char *s;
1711 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001712
Martin v. Löwisffad6332002-11-26 09:28:05 +00001713 if (PyTuple_Size(args) == 1) {
1714 PyObject *o = PyTuple_GetItem(args, 0);
1715 if (PyFloat_Check(o)) {
1716 Py_INCREF(o);
1717 return o;
1718 }
1719 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001720 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001721 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001722 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001723 return Tkinter_Error(self);
1724 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001725}
1726
1727static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001728Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001729{
Barry Warsawfa701a81997-01-16 00:15:11 +00001730 char *s;
1731 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001732
Martin v. Löwisffad6332002-11-26 09:28:05 +00001733 if (PyTuple_Size(args) == 1) {
1734 PyObject *o = PyTuple_GetItem(args, 0);
1735 if (PyInt_Check(o)) {
1736 Py_INCREF(o);
1737 return o;
1738 }
1739 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001740 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001741 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001742 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1743 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001744 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001745}
1746
1747static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001748Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001749{
Barry Warsawfa701a81997-01-16 00:15:11 +00001750 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001751 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001752 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001753
Guido van Rossum43713e52000-02-29 13:59:29 +00001754 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001755 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001756
1757 CHECK_TCL_APPARTMENT;
1758
Guido van Rossum00d93061998-05-28 23:06:38 +00001759 ENTER_TCL
1760 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001761 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001762 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001763 res = Tkinter_Error(self);
1764 else
1765 res = Py_BuildValue("s", Tkapp_Result(self));
1766 LEAVE_OVERLAP_TCL
1767 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001768}
1769
1770static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001771Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001772{
Barry Warsawfa701a81997-01-16 00:15:11 +00001773 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001774 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001775 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001776 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001777
Guido van Rossum43713e52000-02-29 13:59:29 +00001778 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001779 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001780
1781 CHECK_TCL_APPARTMENT;
1782
Guido van Rossum00d93061998-05-28 23:06:38 +00001783 ENTER_TCL
1784 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001785 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001786 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001787 res = Tkinter_Error(self);
1788 else
1789 res = Py_BuildValue("l", v);
1790 LEAVE_OVERLAP_TCL
1791 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001792}
1793
1794static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001795Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001796{
Barry Warsawfa701a81997-01-16 00:15:11 +00001797 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001798 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001799 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001800 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001801
Guido van Rossum43713e52000-02-29 13:59:29 +00001802 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001803 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001804 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001805 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001806 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001807 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001808 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001809 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001810 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001811 res = Tkinter_Error(self);
1812 else
1813 res = Py_BuildValue("d", v);
1814 LEAVE_OVERLAP_TCL
1815 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001816}
1817
1818static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001819Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001820{
Barry Warsawfa701a81997-01-16 00:15:11 +00001821 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001822 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001823 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001824 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001825
Guido van Rossum43713e52000-02-29 13:59:29 +00001826 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001827 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001828 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001829 ENTER_TCL
1830 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001831 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001832 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001833 res = Tkinter_Error(self);
1834 else
1835 res = Py_BuildValue("i", v);
1836 LEAVE_OVERLAP_TCL
1837 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001838}
1839
Barry Warsawfa701a81997-01-16 00:15:11 +00001840
1841
Guido van Rossum18468821994-06-20 07:49:28 +00001842static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001843Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001844{
Barry Warsawfa701a81997-01-16 00:15:11 +00001845 char *list;
1846 int argc;
1847 char **argv;
1848 PyObject *v;
1849 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001850
Martin v. Löwisffad6332002-11-26 09:28:05 +00001851 if (PyTuple_Size(args) == 1) {
1852 v = PyTuple_GetItem(args, 0);
1853 if (PyTuple_Check(v)) {
1854 Py_INCREF(v);
1855 return v;
1856 }
1857 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001858 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001859 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001860
Barry Warsawfa701a81997-01-16 00:15:11 +00001861 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1862 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001863
Barry Warsawfa701a81997-01-16 00:15:11 +00001864 if (!(v = PyTuple_New(argc)))
1865 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001866
Barry Warsawfa701a81997-01-16 00:15:11 +00001867 for (i = 0; i < argc; i++) {
1868 PyObject *s = PyString_FromString(argv[i]);
1869 if (!s || PyTuple_SetItem(v, i, s)) {
1870 Py_DECREF(v);
1871 v = NULL;
1872 goto finally;
1873 }
1874 }
Guido van Rossum18468821994-06-20 07:49:28 +00001875
Barry Warsawfa701a81997-01-16 00:15:11 +00001876 finally:
1877 ckfree(FREECAST argv);
1878 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001879}
1880
1881static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001882Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001883{
Barry Warsawfa701a81997-01-16 00:15:11 +00001884 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001885
Martin v. Löwisffad6332002-11-26 09:28:05 +00001886 if (PyTuple_Size(args) == 1) {
1887 PyObject* o = PyTuple_GetItem(args, 0);
1888 if (PyTuple_Check(o)) {
1889 o = SplitObj(o);
1890 return o;
1891 }
1892 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001893 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001894 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001895 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001896}
1897
1898static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001899Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001900{
Barry Warsawfa701a81997-01-16 00:15:11 +00001901 char *s = Merge(args);
1902 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001903
Barry Warsawfa701a81997-01-16 00:15:11 +00001904 if (s) {
1905 res = PyString_FromString(s);
1906 ckfree(s);
1907 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001908
1909 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001910}
1911
Barry Warsawfa701a81997-01-16 00:15:11 +00001912
1913
Guido van Rossum18468821994-06-20 07:49:28 +00001914/** Tcl Command **/
1915
Guido van Rossum00d93061998-05-28 23:06:38 +00001916/* Client data struct */
1917typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001918 PyObject *self;
1919 PyObject *func;
1920} PythonCmd_ClientData;
1921
1922static int
Fred Drake509d79a2000-07-08 04:04:38 +00001923PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001924{
1925 errorInCmd = 1;
1926 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1927 LEAVE_PYTHON
1928 return TCL_ERROR;
1929}
1930
Guido van Rossum18468821994-06-20 07:49:28 +00001931/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001932 * function or method.
1933 */
Guido van Rossum18468821994-06-20 07:49:28 +00001934static int
Fred Drake509d79a2000-07-08 04:04:38 +00001935PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001936{
Guido van Rossum00d93061998-05-28 23:06:38 +00001937 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001938 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001939 int i, rv;
1940 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001941
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001942 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001943
Barry Warsawfa701a81997-01-16 00:15:11 +00001944 /* TBD: no error checking here since we know, via the
1945 * Tkapp_CreateCommand() that the client data is a two-tuple
1946 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001947 self = data->self;
1948 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001949
Barry Warsawfa701a81997-01-16 00:15:11 +00001950 /* Create argument list (argv1, ..., argvN) */
1951 if (!(arg = PyTuple_New(argc - 1)))
1952 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001953
Barry Warsawfa701a81997-01-16 00:15:11 +00001954 for (i = 0; i < (argc - 1); i++) {
1955 PyObject *s = PyString_FromString(argv[i + 1]);
1956 if (!s || PyTuple_SetItem(arg, i, s)) {
1957 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001958 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001959 }
1960 }
1961 res = PyEval_CallObject(func, arg);
1962 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001963
Barry Warsawfa701a81997-01-16 00:15:11 +00001964 if (res == NULL)
1965 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001966
Barry Warsawfa701a81997-01-16 00:15:11 +00001967 if (!(tmp = PyList_New(0))) {
1968 Py_DECREF(res);
1969 return PythonCmd_Error(interp);
1970 }
1971
Guido van Rossum2834b972000-10-06 16:58:26 +00001972 s = AsString(res, tmp);
1973 if (s == NULL) {
1974 rv = PythonCmd_Error(interp);
1975 }
1976 else {
1977 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1978 rv = TCL_OK;
1979 }
1980
Barry Warsawfa701a81997-01-16 00:15:11 +00001981 Py_DECREF(res);
1982 Py_DECREF(tmp);
1983
Guido van Rossum00d93061998-05-28 23:06:38 +00001984 LEAVE_PYTHON
1985
Guido van Rossum2834b972000-10-06 16:58:26 +00001986 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001987}
1988
1989static void
Fred Drake509d79a2000-07-08 04:04:38 +00001990PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001991{
Guido van Rossum00d93061998-05-28 23:06:38 +00001992 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1993
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001994 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001995 Py_XDECREF(data->self);
1996 Py_XDECREF(data->func);
1997 PyMem_DEL(data);
1998 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001999}
2000
Barry Warsawfa701a81997-01-16 00:15:11 +00002001
2002
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002003
2004TCL_DECLARE_MUTEX(command_mutex)
2005
2006typedef struct CommandEvent{
2007 Tcl_Event ev;
2008 Tcl_Interp* interp;
2009 char *name;
2010 int create;
2011 int *status;
2012 ClientData *data;
2013 Tcl_Condition done;
2014} CommandEvent;
2015
2016static int
2017Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002018{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002019 if (ev->create)
2020 *ev->status = Tcl_CreateCommand(
2021 ev->interp, ev->name, PythonCmd,
2022 ev->data, PythonCmdDelete) == NULL;
2023 else
2024 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2025 Tcl_MutexLock(&command_mutex);
2026 Tcl_ConditionNotify(&ev->done);
2027 Tcl_MutexUnlock(&command_mutex);
2028 return 1;
2029}
2030
2031static PyObject *
2032Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2033{
2034 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002035 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002036 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002037 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002038 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002039
Guido van Rossum43713e52000-02-29 13:59:29 +00002040 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002041 return NULL;
2042 if (!PyCallable_Check(func)) {
2043 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002044 return NULL;
2045 }
Guido van Rossum18468821994-06-20 07:49:28 +00002046
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002047 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002048 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002049 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002050
Guido van Rossum00d93061998-05-28 23:06:38 +00002051 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002052 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002053 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002054 Py_XINCREF(self);
2055 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002056 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002057 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002058
2059 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2060 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2061 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2062 ev->interp = self->interp;
2063 ev->create = 1;
2064 ev->name = cmdName;
2065 ev->data = (ClientData)data;
2066 ev->status = &err;
2067 ev->done = NULL;
2068 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2069 }
2070 else {
2071 ENTER_TCL
2072 err = Tcl_CreateCommand(
2073 Tkapp_Interp(self), cmdName, PythonCmd,
2074 (ClientData)data, PythonCmdDelete) == NULL;
2075 LEAVE_TCL
2076 }
2077 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002078 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002079 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002080 return NULL;
2081 }
Guido van Rossum18468821994-06-20 07:49:28 +00002082
Barry Warsawfa701a81997-01-16 00:15:11 +00002083 Py_INCREF(Py_None);
2084 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002085}
2086
Barry Warsawfa701a81997-01-16 00:15:11 +00002087
2088
Guido van Rossum18468821994-06-20 07:49:28 +00002089static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002090Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002091{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002092 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002093 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002094 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002095
Guido van Rossum43713e52000-02-29 13:59:29 +00002096 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002097 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002098 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2099 CommandEvent *ev;
2100 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2101 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2102 ev->interp = self->interp;
2103 ev->create = 0;
2104 ev->name = cmdName;
2105 ev->status = &err;
2106 ev->done = NULL;
2107 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2108 &command_mutex);
2109 }
2110 else {
2111 ENTER_TCL
2112 err = Tcl_DeleteCommand(self->interp, cmdName);
2113 LEAVE_TCL
2114 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002115 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002116 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2117 return NULL;
2118 }
2119 Py_INCREF(Py_None);
2120 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002121}
2122
Barry Warsawfa701a81997-01-16 00:15:11 +00002123
2124
Guido van Rossum00d93061998-05-28 23:06:38 +00002125#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002126/** File Handler **/
2127
Guido van Rossum00d93061998-05-28 23:06:38 +00002128typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002129 PyObject *func;
2130 PyObject *file;
2131 int id;
2132 struct _fhcdata *next;
2133} FileHandler_ClientData;
2134
2135static FileHandler_ClientData *HeadFHCD;
2136
2137static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002138NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002139{
2140 FileHandler_ClientData *p;
2141 p = PyMem_NEW(FileHandler_ClientData, 1);
2142 if (p != NULL) {
2143 Py_XINCREF(func);
2144 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002145 p->func = func;
2146 p->file = file;
2147 p->id = id;
2148 p->next = HeadFHCD;
2149 HeadFHCD = p;
2150 }
2151 return p;
2152}
2153
2154static void
Fred Drake509d79a2000-07-08 04:04:38 +00002155DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002156{
2157 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002158
2159 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002160 while ((p = *pp) != NULL) {
2161 if (p->id == id) {
2162 *pp = p->next;
2163 Py_XDECREF(p->func);
2164 Py_XDECREF(p->file);
2165 PyMem_DEL(p);
2166 }
2167 else
2168 pp = &p->next;
2169 }
2170}
2171
Guido van Rossuma597dde1995-01-10 20:56:29 +00002172static void
Fred Drake509d79a2000-07-08 04:04:38 +00002173FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002174{
Guido van Rossum00d93061998-05-28 23:06:38 +00002175 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002176 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002177
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002178 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002179 func = data->func;
2180 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002181
Barry Warsawfa701a81997-01-16 00:15:11 +00002182 arg = Py_BuildValue("(Oi)", file, (long) mask);
2183 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002184 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002185
2186 if (res == NULL) {
2187 errorInCmd = 1;
2188 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2189 }
2190 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002191 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002192}
2193
Guido van Rossum18468821994-06-20 07:49:28 +00002194static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002195Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2196 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002197{
Guido van Rossum00d93061998-05-28 23:06:38 +00002198 FileHandler_ClientData *data;
2199 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002200 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002201
Guido van Rossum2834b972000-10-06 16:58:26 +00002202 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2203 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002204 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002205
2206 if (!self && !tcl_lock) {
2207 /* We don't have the Tcl lock since Tcl is threaded. */
2208 PyErr_SetString(PyExc_RuntimeError,
2209 "_tkinter.createfilehandler not supported "
2210 "for threaded Tcl");
2211 return NULL;
2212 }
2213
2214 if (self) {
2215 CHECK_TCL_APPARTMENT;
2216 }
2217
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002218 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002219 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002220 return NULL;
2221 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002222 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002223 return NULL;
2224 }
2225
Guido van Rossuma80649b2000-03-28 20:07:05 +00002226 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002227 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002228 return NULL;
2229
Barry Warsawfa701a81997-01-16 00:15:11 +00002230 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002231 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002232 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002233 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002234 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002235 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002236}
2237
2238static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002239Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002240{
Barry Warsawfa701a81997-01-16 00:15:11 +00002241 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002242 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002243
Guido van Rossum43713e52000-02-29 13:59:29 +00002244 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002245 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002246 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002247 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002248 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002249 return NULL;
2250
Guido van Rossuma80649b2000-03-28 20:07:05 +00002251 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002252
Barry Warsawfa701a81997-01-16 00:15:11 +00002253 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002254 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002255 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002256 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002257 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002258 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002259}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002260#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002261
Barry Warsawfa701a81997-01-16 00:15:11 +00002262
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002263/**** Tktt Object (timer token) ****/
2264
Jeremy Hylton938ace62002-07-17 16:30:39 +00002265static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002266
Guido van Rossum00d93061998-05-28 23:06:38 +00002267typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002268 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002269 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002270 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002271} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002272
2273static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002274Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002275{
Barry Warsawfa701a81997-01-16 00:15:11 +00002276 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002277 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002278
Guido van Rossum43713e52000-02-29 13:59:29 +00002279 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002280 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002281 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002282 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002283 v->token = NULL;
2284 }
2285 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002286 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002287 Py_DECREF(func);
2288 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002289 }
2290 Py_INCREF(Py_None);
2291 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002292}
2293
2294static PyMethodDef Tktt_methods[] =
2295{
Neal Norwitzb0493252002-03-31 14:44:22 +00002296 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002297 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002298};
2299
2300static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002301Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002302{
Barry Warsawfa701a81997-01-16 00:15:11 +00002303 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002304
Guido van Rossumb18618d2000-05-03 23:44:39 +00002305 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002306 if (v == NULL)
2307 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002308
Guido van Rossum00d93061998-05-28 23:06:38 +00002309 Py_INCREF(func);
2310 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002311 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002312
2313 /* Extra reference, deleted when called or when handler is deleted */
2314 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002315 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002316}
2317
2318static void
Fred Drake509d79a2000-07-08 04:04:38 +00002319Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002320{
Guido van Rossum00d93061998-05-28 23:06:38 +00002321 TkttObject *v = (TkttObject *)self;
2322 PyObject *func = v->func;
2323
2324 Py_XDECREF(func);
2325
Guido van Rossumb18618d2000-05-03 23:44:39 +00002326 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002327}
2328
Guido van Rossum597ac201998-05-12 14:36:19 +00002329static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002330Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002331{
Barry Warsawfa701a81997-01-16 00:15:11 +00002332 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002333 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002334
Tim Peters885d4572001-11-28 20:27:42 +00002335 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002336 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002337 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002338}
2339
2340static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002341Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002342{
Barry Warsawfa701a81997-01-16 00:15:11 +00002343 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002344}
2345
2346static PyTypeObject Tktt_Type =
2347{
Guido van Rossum35d43371997-08-02 00:09:09 +00002348 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002349 0, /*ob_size */
2350 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002351 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002352 0, /*tp_itemsize */
2353 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002354 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002355 Tktt_GetAttr, /*tp_getattr */
2356 0, /*tp_setattr */
2357 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002358 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002359 0, /*tp_as_number */
2360 0, /*tp_as_sequence */
2361 0, /*tp_as_mapping */
2362 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002363};
2364
Barry Warsawfa701a81997-01-16 00:15:11 +00002365
2366
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002367/** Timer Handler **/
2368
2369static void
Fred Drake509d79a2000-07-08 04:04:38 +00002370TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002371{
Guido van Rossum00d93061998-05-28 23:06:38 +00002372 TkttObject *v = (TkttObject *)clientData;
2373 PyObject *func = v->func;
2374 PyObject *res;
2375
2376 if (func == NULL)
2377 return;
2378
2379 v->func = NULL;
2380
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002381 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002382
2383 res = PyEval_CallObject(func, NULL);
2384 Py_DECREF(func);
2385 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002386
Barry Warsawfa701a81997-01-16 00:15:11 +00002387 if (res == NULL) {
2388 errorInCmd = 1;
2389 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2390 }
2391 else
2392 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002393
2394 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002395}
2396
2397static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002398Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002399{
Barry Warsawfa701a81997-01-16 00:15:11 +00002400 int milliseconds;
2401 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002402 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002403
Guido van Rossum2834b972000-10-06 16:58:26 +00002404 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2405 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002406 return NULL;
2407 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002408 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002409 return NULL;
2410 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002411
2412 if (!self && !tcl_lock) {
2413 /* We don't have the Tcl lock since Tcl is threaded. */
2414 PyErr_SetString(PyExc_RuntimeError,
2415 "_tkinter.createtimerhandler not supported "
2416 "for threaded Tcl");
2417 return NULL;
2418 }
2419
2420 if (self) {
2421 CHECK_TCL_APPARTMENT;
2422 }
2423
Guido van Rossum00d93061998-05-28 23:06:38 +00002424 v = Tktt_New(func);
2425 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2426 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002427
Guido van Rossum00d93061998-05-28 23:06:38 +00002428 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002429}
2430
Barry Warsawfa701a81997-01-16 00:15:11 +00002431
Guido van Rossum18468821994-06-20 07:49:28 +00002432/** Event Loop **/
2433
Guido van Rossum18468821994-06-20 07:49:28 +00002434static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002435Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002436{
Barry Warsawfa701a81997-01-16 00:15:11 +00002437 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002438 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002439#ifdef WITH_THREAD
2440 PyThreadState *tstate = PyThreadState_Get();
2441#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002442
Guido van Rossum43713e52000-02-29 13:59:29 +00002443 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002444 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002445
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002446 if (!self && !tcl_lock) {
2447 /* We don't have the Tcl lock since Tcl is threaded. */
2448 PyErr_SetString(PyExc_RuntimeError,
2449 "_tkinter.mainloop not supported "
2450 "for threaded Tcl");
2451 return NULL;
2452 }
2453
2454 if (self) {
2455 CHECK_TCL_APPARTMENT;
2456 self->dispatching = 1;
2457 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002458
Barry Warsawfa701a81997-01-16 00:15:11 +00002459 quitMainLoop = 0;
2460 while (Tk_GetNumMainWindows() > threshold &&
2461 !quitMainLoop &&
2462 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002463 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002464 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002465
2466#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002467 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002468 /* Allow other Python threads to run. */
2469 ENTER_TCL
2470 result = Tcl_DoOneEvent(0);
2471 LEAVE_TCL
2472 }
2473 else {
2474 Py_BEGIN_ALLOW_THREADS
2475 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2476 tcl_tstate = tstate;
2477 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2478 tcl_tstate = NULL;
2479 if(tcl_lock)PyThread_release_lock(tcl_lock);
2480 if (result == 0)
2481 Sleep(20);
2482 Py_END_ALLOW_THREADS
2483 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002484#else
2485 result = Tcl_DoOneEvent(0);
2486#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002487
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002488 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002489 if (self)
2490 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002491 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002492 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002493 if (result < 0)
2494 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002495 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002496 if (self)
2497 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002498 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002499
Barry Warsawfa701a81997-01-16 00:15:11 +00002500 if (errorInCmd) {
2501 errorInCmd = 0;
2502 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2503 excInCmd = valInCmd = trbInCmd = NULL;
2504 return NULL;
2505 }
2506 Py_INCREF(Py_None);
2507 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002508}
2509
2510static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002511Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002512{
Guido van Rossum35d43371997-08-02 00:09:09 +00002513 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002514 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002515
Guido van Rossum43713e52000-02-29 13:59:29 +00002516 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002517 return NULL;
2518
Guido van Rossum00d93061998-05-28 23:06:38 +00002519 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002520 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002521 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002522 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002523}
2524
2525static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002526Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002527{
2528
Guido van Rossum43713e52000-02-29 13:59:29 +00002529 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002530 return NULL;
2531
2532 quitMainLoop = 1;
2533 Py_INCREF(Py_None);
2534 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002535}
2536
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002537static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002538Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002539{
2540
Guido van Rossum43713e52000-02-29 13:59:29 +00002541 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002542 return NULL;
2543
2544 return PyInt_FromLong((long)Tkapp_Interp(self));
2545}
2546
Barry Warsawfa701a81997-01-16 00:15:11 +00002547
Martin v. Löwisffad6332002-11-26 09:28:05 +00002548static PyObject *
2549Tkapp_WantObjects(PyObject *self, PyObject *args)
2550{
2551
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002552 int wantobjects;
2553 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002554 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002555 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002556
2557 Py_INCREF(Py_None);
2558 return Py_None;
2559}
2560
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002561static PyObject *
2562Tkapp_WillDispatch(PyObject *self, PyObject *args)
2563{
2564
2565 ((TkappObject*)self)->dispatching = 1;
2566
2567 Py_INCREF(Py_None);
2568 return Py_None;
2569}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002570
Barry Warsawfa701a81997-01-16 00:15:11 +00002571
Guido van Rossum18468821994-06-20 07:49:28 +00002572/**** Tkapp Method List ****/
2573
2574static PyMethodDef Tkapp_methods[] =
2575{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002576 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002577 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002578 {"call", Tkapp_Call, METH_OLDARGS},
2579 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2580 {"eval", Tkapp_Eval, METH_VARARGS},
2581 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2582 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2583 {"record", Tkapp_Record, METH_VARARGS},
2584 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2585 {"setvar", Tkapp_SetVar, METH_VARARGS},
2586 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2587 {"getvar", Tkapp_GetVar, METH_VARARGS},
2588 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2589 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2590 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2591 {"getint", Tkapp_GetInt, METH_VARARGS},
2592 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2593 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2594 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2595 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2596 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2597 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2598 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2599 {"split", Tkapp_Split, METH_VARARGS},
2600 {"merge", Tkapp_Merge, METH_OLDARGS},
2601 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2602 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002603#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002604 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2605 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002606#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002607 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2608 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2609 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2610 {"quit", Tkapp_Quit, METH_VARARGS},
2611 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002612 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002613};
2614
Barry Warsawfa701a81997-01-16 00:15:11 +00002615
2616
Guido van Rossum18468821994-06-20 07:49:28 +00002617/**** Tkapp Type Methods ****/
2618
2619static void
Fred Drake509d79a2000-07-08 04:04:38 +00002620Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002621{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002622 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002623 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002624 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002625 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002626 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002627 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002628}
2629
2630static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002631Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002632{
Guido van Rossum35d43371997-08-02 00:09:09 +00002633 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002634}
2635
2636static PyTypeObject Tkapp_Type =
2637{
Guido van Rossum35d43371997-08-02 00:09:09 +00002638 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002639 0, /*ob_size */
2640 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002641 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002642 0, /*tp_itemsize */
2643 Tkapp_Dealloc, /*tp_dealloc */
2644 0, /*tp_print */
2645 Tkapp_GetAttr, /*tp_getattr */
2646 0, /*tp_setattr */
2647 0, /*tp_compare */
2648 0, /*tp_repr */
2649 0, /*tp_as_number */
2650 0, /*tp_as_sequence */
2651 0, /*tp_as_mapping */
2652 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002653};
2654
Barry Warsawfa701a81997-01-16 00:15:11 +00002655
2656
Guido van Rossum18468821994-06-20 07:49:28 +00002657/**** Tkinter Module ****/
2658
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002659typedef struct {
2660 PyObject* tuple;
2661 int size; /* current size */
2662 int maxsize; /* allocated size */
2663} FlattenContext;
2664
2665static int
2666_bump(FlattenContext* context, int size)
2667{
Guido van Rossum2834b972000-10-06 16:58:26 +00002668 /* expand tuple to hold (at least) size new items.
2669 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002670
2671 int maxsize = context->maxsize * 2;
2672
2673 if (maxsize < context->size + size)
2674 maxsize = context->size + size;
2675
2676 context->maxsize = maxsize;
2677
Tim Peters4324aa32001-05-28 22:30:08 +00002678 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002679}
2680
2681static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002682_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002683{
2684 /* add tuple or list to argument tuple (recursively) */
2685
2686 int i, size;
2687
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002688 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002689 PyErr_SetString(PyExc_ValueError,
2690 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002691 return 0;
2692 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002693 size = PyList_GET_SIZE(item);
2694 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002695 if (context->size + size > context->maxsize &&
2696 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002697 return 0;
2698 /* copy items to output tuple */
2699 for (i = 0; i < size; i++) {
2700 PyObject *o = PyList_GET_ITEM(item, i);
2701 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002702 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002703 return 0;
2704 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002705 if (context->size + 1 > context->maxsize &&
2706 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002707 return 0;
2708 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002709 PyTuple_SET_ITEM(context->tuple,
2710 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002711 }
2712 }
2713 } else if (PyTuple_Check(item)) {
2714 /* same, for tuples */
2715 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002716 if (context->size + size > context->maxsize &&
2717 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002718 return 0;
2719 for (i = 0; i < size; i++) {
2720 PyObject *o = PyTuple_GET_ITEM(item, i);
2721 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002722 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002723 return 0;
2724 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002725 if (context->size + 1 > context->maxsize &&
2726 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002727 return 0;
2728 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002729 PyTuple_SET_ITEM(context->tuple,
2730 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002731 }
2732 }
2733 } else {
2734 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2735 return 0;
2736 }
2737 return 1;
2738}
2739
2740static PyObject *
2741Tkinter_Flatten(PyObject* self, PyObject* args)
2742{
2743 FlattenContext context;
2744 PyObject* item;
2745
2746 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2747 return NULL;
2748
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002749 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002750 if (context.maxsize <= 0)
2751 return PyTuple_New(0);
2752
2753 context.tuple = PyTuple_New(context.maxsize);
2754 if (!context.tuple)
2755 return NULL;
2756
2757 context.size = 0;
2758
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002759 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002760 return NULL;
2761
Tim Peters4324aa32001-05-28 22:30:08 +00002762 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002763 return NULL;
2764
2765 return context.tuple;
2766}
2767
Guido van Rossum18468821994-06-20 07:49:28 +00002768static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002769Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002770{
Barry Warsawfa701a81997-01-16 00:15:11 +00002771 char *screenName = NULL;
2772 char *baseName = NULL;
2773 char *className = NULL;
2774 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002775 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002776
Guido van Rossum35d43371997-08-02 00:09:09 +00002777 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002778 if (baseName != NULL)
2779 baseName++;
2780 else
2781 baseName = Py_GetProgramName();
2782 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002783
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002784 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002785 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002786 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002787 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002788
Barry Warsawfa701a81997-01-16 00:15:11 +00002789 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002790 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002791}
2792
2793static PyMethodDef moduleMethods[] =
2794{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002795 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2796 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002797#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002798 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2799 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002800#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002801 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2802 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2803 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2804 {"quit", Tkapp_Quit, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002805 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002806};
2807
Guido van Rossum7bf15641998-05-22 18:28:17 +00002808#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002809
2810static int stdin_ready = 0;
2811
Guido van Rossumad4db171998-06-13 13:56:28 +00002812#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002813static void
Fred Drake509d79a2000-07-08 04:04:38 +00002814MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002815{
2816 stdin_ready = 1;
2817}
Guido van Rossumad4db171998-06-13 13:56:28 +00002818#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002819
Guido van Rossum00d93061998-05-28 23:06:38 +00002820static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002821
Guido van Rossum18468821994-06-20 07:49:28 +00002822static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002823EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002824{
Guido van Rossumad4db171998-06-13 13:56:28 +00002825#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002826 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002827#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002828#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002829 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002830#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002831 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002832 errorInCmd = 0;
2833#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002834 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002835 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002836#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002837 while (!errorInCmd && !stdin_ready) {
2838 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002839#ifdef MS_WINDOWS
2840 if (_kbhit()) {
2841 stdin_ready = 1;
2842 break;
2843 }
2844#endif
2845#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002846 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002847 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002848 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002849
Guido van Rossum00d93061998-05-28 23:06:38 +00002850 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002851
2852 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002853 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002854 if (result == 0)
2855 Sleep(20);
2856 Py_END_ALLOW_THREADS
2857#else
2858 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002859#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002860
2861 if (result < 0)
2862 break;
2863 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002864#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002865 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002866#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002867 if (errorInCmd) {
2868 errorInCmd = 0;
2869 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2870 excInCmd = valInCmd = trbInCmd = NULL;
2871 PyErr_Print();
2872 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002873#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002874 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002875#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002876 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002877}
Guido van Rossum18468821994-06-20 07:49:28 +00002878
Guido van Rossum00d93061998-05-28 23:06:38 +00002879#endif
2880
Guido van Rossum7bf15641998-05-22 18:28:17 +00002881static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002882EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002883{
Guido van Rossum00d93061998-05-28 23:06:38 +00002884#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002885 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002886#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002887 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002888#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002889 PyOS_InputHook = EventHook;
2890 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002891#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002892}
2893
2894static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002895DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002896{
Guido van Rossum00d93061998-05-28 23:06:38 +00002897#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002898 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2899 PyOS_InputHook = NULL;
2900 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002901#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002902}
2903
Barry Warsawfa701a81997-01-16 00:15:11 +00002904
2905/* all errors will be checked in one fell swoop in init_tkinter() */
2906static void
Fred Drake509d79a2000-07-08 04:04:38 +00002907ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002908{
2909 PyObject *v = PyInt_FromLong(val);
2910 if (v) {
2911 PyDict_SetItemString(d, name, v);
2912 Py_DECREF(v);
2913 }
2914}
2915static void
Fred Drake509d79a2000-07-08 04:04:38 +00002916ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002917{
2918 PyObject *v = PyString_FromString(val);
2919 if (v) {
2920 PyDict_SetItemString(d, name, v);
2921 Py_DECREF(v);
2922 }
2923}
2924
2925
Mark Hammond62b1ab12002-07-23 06:31:15 +00002926PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002927init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002928{
Barry Warsawfa701a81997-01-16 00:15:11 +00002929 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002930
Barry Warsawfa701a81997-01-16 00:15:11 +00002931 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002932
2933#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002934 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002935#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002936
Barry Warsawfa701a81997-01-16 00:15:11 +00002937 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002938
Barry Warsawfa701a81997-01-16 00:15:11 +00002939 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00002940 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00002941 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002942
Guido van Rossum35d43371997-08-02 00:09:09 +00002943 ins_long(d, "READABLE", TCL_READABLE);
2944 ins_long(d, "WRITABLE", TCL_WRITABLE);
2945 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2946 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2947 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2948 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2949 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2950 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2951 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002952 ins_string(d, "TK_VERSION", TK_VERSION);
2953 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002954
Guido van Rossum83551bf1997-09-13 00:44:23 +00002955 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002956
2957 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002958 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2959
Martin v. Löwisffad6332002-11-26 09:28:05 +00002960 PyTclObject_Type.ob_type = &PyType_Type;
2961 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002962
2963#ifdef TK_AQUA
2964 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2965 * start waking up. Note that Tcl_FindExecutable will do this, this
2966 * code must be above it! The original warning from
2967 * tkMacOSXAppInit.c is copied below.
2968 *
2969 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2970 * Tcl interpreter for now. It probably should work to do this
2971 * in the other order, but for now it doesn't seem to.
2972 *
2973 */
2974 Tk_MacOSXSetupTkNotifier();
2975#endif
2976
2977
Guido van Rossume187b0e2000-03-27 21:46:29 +00002978 /* This helps the dynamic loader; in Unicode aware Tcl versions
2979 it also helps Tcl find its encodings. */
2980 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00002981
Barry Warsawfa701a81997-01-16 00:15:11 +00002982 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002983 return;
2984
Guido van Rossum43ff8681998-07-14 18:02:13 +00002985#if 0
2986 /* This was not a good idea; through <Destroy> bindings,
2987 Tcl_Finalize() may invoke Python code but at that point the
2988 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002989 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002990#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002991
Jack Jansen34cc5c31995-10-31 16:15:12 +00002992#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002993 /*
2994 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2995 ** Most of the initializations in that routine (toolbox init calls and
2996 ** such) have already been done for us, so we only need these.
2997 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002998 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002999
3000 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00003001#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00003002 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00003003#endif /* GENERATINGCFM */
3004#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00003005}
Guido van Rossum9722ad81995-09-22 23:49:28 +00003006
Guido van Rossumec22c921996-02-25 04:50:29 +00003007
Barry Warsawfa701a81997-01-16 00:15:11 +00003008
Guido van Rossum9722ad81995-09-22 23:49:28 +00003009#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003010
3011/*
Guido van Rossumec22c921996-02-25 04:50:29 +00003012** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003013*/
3014
Guido van Rossum9722ad81995-09-22 23:49:28 +00003015void
3016panic(char * format, ...)
3017{
Barry Warsawfa701a81997-01-16 00:15:11 +00003018 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003019
Barry Warsawfa701a81997-01-16 00:15:11 +00003020 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003021
Guido van Rossum227cf761998-08-05 13:53:32 +00003022 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00003023 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003024
Barry Warsawfa701a81997-01-16 00:15:11 +00003025 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003026
Barry Warsawfa701a81997-01-16 00:15:11 +00003027 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00003028}
Jack Jansen40b546d1995-11-14 10:34:45 +00003029
Guido van Rossumec22c921996-02-25 04:50:29 +00003030/*
3031** Pass events to SIOUX before passing them to Tk.
3032*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003033
Guido van Rossumec22c921996-02-25 04:50:29 +00003034static int
Fred Drake509d79a2000-07-08 04:04:38 +00003035PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003036{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003037 WindowPtr frontwin;
3038 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00003039 ** Sioux eats too many events, so we don't pass it everything. We
3040 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003041 ** the Sioux window is frontmost. This means that Tk menus don't work
3042 ** in that case, but at least we can scroll the sioux window.
3043 ** Note that the SIOUXIsAppWindow() routine we use here is not really
3044 ** part of the external interface of Sioux...
3045 */
3046 frontwin = FrontWindow();
3047 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
3048 if (SIOUXHandleOneEvent(eventPtr))
3049 return 0; /* Nothing happened to the Tcl event queue */
3050 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003051 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003052}
3053
Guido van Rossumec22c921996-02-25 04:50:29 +00003054#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003055
3056/*
3057** Additional Mac specific code for dealing with shared libraries.
3058*/
3059
3060#include <Resources.h>
3061#include <CodeFragments.h>
3062
3063static int loaded_from_shlib = 0;
3064static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003065
Jack Jansen34cc5c31995-10-31 16:15:12 +00003066/*
3067** If this module is dynamically loaded the following routine should
3068** be the init routine. It takes care of adding the shared library to
3069** the resource-file chain, so that the tk routines can find their
3070** resources.
3071*/
3072OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003073init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003074{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00003075 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00003076 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003077 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003078 library_fss = *data->fragLocator.u.onDisk.fileSpec;
3079 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003080 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003081 library_fss = *data->fragLocator.u.inSegs.fileSpec;
3082 loaded_from_shlib = 1;
3083 }
3084 return noErr;
3085}
3086
3087/*
3088** Insert the library resources into the search path. Put them after
3089** the resources from the application. Again, we ignore errors.
3090*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003091static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003092mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003093{
3094 if ( !loaded_from_shlib )
3095 return;
3096 (void)FSpOpenResFile(&library_fss, fsRdPerm);
3097}
3098
Guido van Rossumec22c921996-02-25 04:50:29 +00003099#endif /* GENERATINGCFM */
3100#endif /* macintosh */