blob: 100e06f227ff2f0055e3c4852ef9559f4307211a [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;
Neal Norwitz12e22172003-03-03 21:16:39 +00002246
2247 if (!self && !tcl_lock) {
2248 /* We don't have the Tcl lock since Tcl is threaded. */
2249 PyErr_SetString(PyExc_RuntimeError,
2250 "_tkinter.deletefilehandler not supported "
2251 "for threaded Tcl");
2252 return NULL;
2253 }
2254
2255 if (self) {
2256 CHECK_TCL_APPARTMENT;
2257 }
2258
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002259 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002260 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002261 return NULL;
2262
Guido van Rossuma80649b2000-03-28 20:07:05 +00002263 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002264
Barry Warsawfa701a81997-01-16 00:15:11 +00002265 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002266 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002267 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002268 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002269 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002270 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002271}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002272#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002273
Barry Warsawfa701a81997-01-16 00:15:11 +00002274
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002275/**** Tktt Object (timer token) ****/
2276
Jeremy Hylton938ace62002-07-17 16:30:39 +00002277static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002278
Guido van Rossum00d93061998-05-28 23:06:38 +00002279typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002280 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002281 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002282 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002283} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002284
2285static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002286Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002287{
Barry Warsawfa701a81997-01-16 00:15:11 +00002288 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002289 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002290
Guido van Rossum43713e52000-02-29 13:59:29 +00002291 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002292 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002293 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002294 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002295 v->token = NULL;
2296 }
2297 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002298 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002299 Py_DECREF(func);
2300 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002301 }
2302 Py_INCREF(Py_None);
2303 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002304}
2305
2306static PyMethodDef Tktt_methods[] =
2307{
Neal Norwitzb0493252002-03-31 14:44:22 +00002308 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002309 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002310};
2311
2312static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002313Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002314{
Barry Warsawfa701a81997-01-16 00:15:11 +00002315 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002316
Guido van Rossumb18618d2000-05-03 23:44:39 +00002317 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002318 if (v == NULL)
2319 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002320
Guido van Rossum00d93061998-05-28 23:06:38 +00002321 Py_INCREF(func);
2322 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002323 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002324
2325 /* Extra reference, deleted when called or when handler is deleted */
2326 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002327 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002328}
2329
2330static void
Fred Drake509d79a2000-07-08 04:04:38 +00002331Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002332{
Guido van Rossum00d93061998-05-28 23:06:38 +00002333 TkttObject *v = (TkttObject *)self;
2334 PyObject *func = v->func;
2335
2336 Py_XDECREF(func);
2337
Guido van Rossumb18618d2000-05-03 23:44:39 +00002338 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002339}
2340
Guido van Rossum597ac201998-05-12 14:36:19 +00002341static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002342Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002343{
Barry Warsawfa701a81997-01-16 00:15:11 +00002344 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002345 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002346
Tim Peters885d4572001-11-28 20:27:42 +00002347 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002348 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002349 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002350}
2351
2352static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002353Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002354{
Barry Warsawfa701a81997-01-16 00:15:11 +00002355 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002356}
2357
2358static PyTypeObject Tktt_Type =
2359{
Guido van Rossum35d43371997-08-02 00:09:09 +00002360 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002361 0, /*ob_size */
2362 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002363 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002364 0, /*tp_itemsize */
2365 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002366 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002367 Tktt_GetAttr, /*tp_getattr */
2368 0, /*tp_setattr */
2369 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002370 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002371 0, /*tp_as_number */
2372 0, /*tp_as_sequence */
2373 0, /*tp_as_mapping */
2374 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002375};
2376
Barry Warsawfa701a81997-01-16 00:15:11 +00002377
2378
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002379/** Timer Handler **/
2380
2381static void
Fred Drake509d79a2000-07-08 04:04:38 +00002382TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002383{
Guido van Rossum00d93061998-05-28 23:06:38 +00002384 TkttObject *v = (TkttObject *)clientData;
2385 PyObject *func = v->func;
2386 PyObject *res;
2387
2388 if (func == NULL)
2389 return;
2390
2391 v->func = NULL;
2392
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002393 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002394
2395 res = PyEval_CallObject(func, NULL);
2396 Py_DECREF(func);
2397 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002398
Barry Warsawfa701a81997-01-16 00:15:11 +00002399 if (res == NULL) {
2400 errorInCmd = 1;
2401 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2402 }
2403 else
2404 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002405
2406 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002407}
2408
2409static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002410Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002411{
Barry Warsawfa701a81997-01-16 00:15:11 +00002412 int milliseconds;
2413 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002414 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002415
Guido van Rossum2834b972000-10-06 16:58:26 +00002416 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2417 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002418 return NULL;
2419 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002420 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002421 return NULL;
2422 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002423
2424 if (!self && !tcl_lock) {
2425 /* We don't have the Tcl lock since Tcl is threaded. */
2426 PyErr_SetString(PyExc_RuntimeError,
2427 "_tkinter.createtimerhandler not supported "
2428 "for threaded Tcl");
2429 return NULL;
2430 }
2431
2432 if (self) {
2433 CHECK_TCL_APPARTMENT;
2434 }
2435
Guido van Rossum00d93061998-05-28 23:06:38 +00002436 v = Tktt_New(func);
2437 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2438 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002439
Guido van Rossum00d93061998-05-28 23:06:38 +00002440 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002441}
2442
Barry Warsawfa701a81997-01-16 00:15:11 +00002443
Guido van Rossum18468821994-06-20 07:49:28 +00002444/** Event Loop **/
2445
Guido van Rossum18468821994-06-20 07:49:28 +00002446static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002447Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002448{
Barry Warsawfa701a81997-01-16 00:15:11 +00002449 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002450 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002451#ifdef WITH_THREAD
2452 PyThreadState *tstate = PyThreadState_Get();
2453#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002454
Guido van Rossum43713e52000-02-29 13:59:29 +00002455 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002456 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002457
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002458 if (!self && !tcl_lock) {
2459 /* We don't have the Tcl lock since Tcl is threaded. */
2460 PyErr_SetString(PyExc_RuntimeError,
2461 "_tkinter.mainloop not supported "
2462 "for threaded Tcl");
2463 return NULL;
2464 }
2465
2466 if (self) {
2467 CHECK_TCL_APPARTMENT;
2468 self->dispatching = 1;
2469 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002470
Barry Warsawfa701a81997-01-16 00:15:11 +00002471 quitMainLoop = 0;
2472 while (Tk_GetNumMainWindows() > threshold &&
2473 !quitMainLoop &&
2474 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002475 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002476 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002477
2478#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002479 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002480 /* Allow other Python threads to run. */
2481 ENTER_TCL
2482 result = Tcl_DoOneEvent(0);
2483 LEAVE_TCL
2484 }
2485 else {
2486 Py_BEGIN_ALLOW_THREADS
2487 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2488 tcl_tstate = tstate;
2489 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2490 tcl_tstate = NULL;
2491 if(tcl_lock)PyThread_release_lock(tcl_lock);
2492 if (result == 0)
2493 Sleep(20);
2494 Py_END_ALLOW_THREADS
2495 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002496#else
2497 result = Tcl_DoOneEvent(0);
2498#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002499
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002500 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002501 if (self)
2502 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002503 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002504 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002505 if (result < 0)
2506 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002507 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002508 if (self)
2509 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002510 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002511
Barry Warsawfa701a81997-01-16 00:15:11 +00002512 if (errorInCmd) {
2513 errorInCmd = 0;
2514 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2515 excInCmd = valInCmd = trbInCmd = NULL;
2516 return NULL;
2517 }
2518 Py_INCREF(Py_None);
2519 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002520}
2521
2522static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002523Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002524{
Guido van Rossum35d43371997-08-02 00:09:09 +00002525 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002526 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002527
Guido van Rossum43713e52000-02-29 13:59:29 +00002528 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002529 return NULL;
2530
Guido van Rossum00d93061998-05-28 23:06:38 +00002531 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002532 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002533 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002534 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002535}
2536
2537static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002538Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002539{
2540
Guido van Rossum43713e52000-02-29 13:59:29 +00002541 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002542 return NULL;
2543
2544 quitMainLoop = 1;
2545 Py_INCREF(Py_None);
2546 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002547}
2548
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002549static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002550Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002551{
2552
Guido van Rossum43713e52000-02-29 13:59:29 +00002553 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002554 return NULL;
2555
2556 return PyInt_FromLong((long)Tkapp_Interp(self));
2557}
2558
Barry Warsawfa701a81997-01-16 00:15:11 +00002559
Martin v. Löwisffad6332002-11-26 09:28:05 +00002560static PyObject *
2561Tkapp_WantObjects(PyObject *self, PyObject *args)
2562{
2563
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002564 int wantobjects;
2565 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002566 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002567 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002568
2569 Py_INCREF(Py_None);
2570 return Py_None;
2571}
2572
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002573static PyObject *
2574Tkapp_WillDispatch(PyObject *self, PyObject *args)
2575{
2576
2577 ((TkappObject*)self)->dispatching = 1;
2578
2579 Py_INCREF(Py_None);
2580 return Py_None;
2581}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002582
Barry Warsawfa701a81997-01-16 00:15:11 +00002583
Guido van Rossum18468821994-06-20 07:49:28 +00002584/**** Tkapp Method List ****/
2585
2586static PyMethodDef Tkapp_methods[] =
2587{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002588 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002589 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002590 {"call", Tkapp_Call, METH_OLDARGS},
2591 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2592 {"eval", Tkapp_Eval, METH_VARARGS},
2593 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2594 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2595 {"record", Tkapp_Record, METH_VARARGS},
2596 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2597 {"setvar", Tkapp_SetVar, METH_VARARGS},
2598 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2599 {"getvar", Tkapp_GetVar, METH_VARARGS},
2600 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2601 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2602 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2603 {"getint", Tkapp_GetInt, METH_VARARGS},
2604 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2605 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2606 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2607 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2608 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2609 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2610 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2611 {"split", Tkapp_Split, METH_VARARGS},
2612 {"merge", Tkapp_Merge, METH_OLDARGS},
2613 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2614 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002615#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002616 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2617 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002618#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002619 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2620 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2621 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2622 {"quit", Tkapp_Quit, METH_VARARGS},
2623 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002624 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002625};
2626
Barry Warsawfa701a81997-01-16 00:15:11 +00002627
2628
Guido van Rossum18468821994-06-20 07:49:28 +00002629/**** Tkapp Type Methods ****/
2630
2631static void
Fred Drake509d79a2000-07-08 04:04:38 +00002632Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002633{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002634 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002635 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002636 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002637 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002638 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002639 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002640}
2641
2642static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002643Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002644{
Guido van Rossum35d43371997-08-02 00:09:09 +00002645 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002646}
2647
2648static PyTypeObject Tkapp_Type =
2649{
Guido van Rossum35d43371997-08-02 00:09:09 +00002650 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002651 0, /*ob_size */
2652 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002653 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002654 0, /*tp_itemsize */
2655 Tkapp_Dealloc, /*tp_dealloc */
2656 0, /*tp_print */
2657 Tkapp_GetAttr, /*tp_getattr */
2658 0, /*tp_setattr */
2659 0, /*tp_compare */
2660 0, /*tp_repr */
2661 0, /*tp_as_number */
2662 0, /*tp_as_sequence */
2663 0, /*tp_as_mapping */
2664 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002665};
2666
Barry Warsawfa701a81997-01-16 00:15:11 +00002667
2668
Guido van Rossum18468821994-06-20 07:49:28 +00002669/**** Tkinter Module ****/
2670
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002671typedef struct {
2672 PyObject* tuple;
2673 int size; /* current size */
2674 int maxsize; /* allocated size */
2675} FlattenContext;
2676
2677static int
2678_bump(FlattenContext* context, int size)
2679{
Guido van Rossum2834b972000-10-06 16:58:26 +00002680 /* expand tuple to hold (at least) size new items.
2681 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002682
2683 int maxsize = context->maxsize * 2;
2684
2685 if (maxsize < context->size + size)
2686 maxsize = context->size + size;
2687
2688 context->maxsize = maxsize;
2689
Tim Peters4324aa32001-05-28 22:30:08 +00002690 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002691}
2692
2693static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002694_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002695{
2696 /* add tuple or list to argument tuple (recursively) */
2697
2698 int i, size;
2699
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002700 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002701 PyErr_SetString(PyExc_ValueError,
2702 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002703 return 0;
2704 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002705 size = PyList_GET_SIZE(item);
2706 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002707 if (context->size + size > context->maxsize &&
2708 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002709 return 0;
2710 /* copy items to output tuple */
2711 for (i = 0; i < size; i++) {
2712 PyObject *o = PyList_GET_ITEM(item, i);
2713 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002714 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002715 return 0;
2716 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002717 if (context->size + 1 > context->maxsize &&
2718 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002719 return 0;
2720 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002721 PyTuple_SET_ITEM(context->tuple,
2722 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002723 }
2724 }
2725 } else if (PyTuple_Check(item)) {
2726 /* same, for tuples */
2727 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002728 if (context->size + size > context->maxsize &&
2729 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002730 return 0;
2731 for (i = 0; i < size; i++) {
2732 PyObject *o = PyTuple_GET_ITEM(item, i);
2733 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002734 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002735 return 0;
2736 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002737 if (context->size + 1 > context->maxsize &&
2738 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002739 return 0;
2740 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002741 PyTuple_SET_ITEM(context->tuple,
2742 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002743 }
2744 }
2745 } else {
2746 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2747 return 0;
2748 }
2749 return 1;
2750}
2751
2752static PyObject *
2753Tkinter_Flatten(PyObject* self, PyObject* args)
2754{
2755 FlattenContext context;
2756 PyObject* item;
2757
2758 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2759 return NULL;
2760
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002761 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002762 if (context.maxsize <= 0)
2763 return PyTuple_New(0);
2764
2765 context.tuple = PyTuple_New(context.maxsize);
2766 if (!context.tuple)
2767 return NULL;
2768
2769 context.size = 0;
2770
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002771 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002772 return NULL;
2773
Tim Peters4324aa32001-05-28 22:30:08 +00002774 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002775 return NULL;
2776
2777 return context.tuple;
2778}
2779
Guido van Rossum18468821994-06-20 07:49:28 +00002780static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002781Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002782{
Barry Warsawfa701a81997-01-16 00:15:11 +00002783 char *screenName = NULL;
2784 char *baseName = NULL;
2785 char *className = NULL;
2786 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002787 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002788
Guido van Rossum35d43371997-08-02 00:09:09 +00002789 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002790 if (baseName != NULL)
2791 baseName++;
2792 else
2793 baseName = Py_GetProgramName();
2794 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002795
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002796 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002797 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002798 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002799 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002800
Barry Warsawfa701a81997-01-16 00:15:11 +00002801 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002802 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002803}
2804
2805static PyMethodDef moduleMethods[] =
2806{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002807 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2808 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002809#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002810 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2811 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002812#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002813 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2814 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2815 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2816 {"quit", Tkapp_Quit, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002817 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002818};
2819
Guido van Rossum7bf15641998-05-22 18:28:17 +00002820#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002821
2822static int stdin_ready = 0;
2823
Guido van Rossumad4db171998-06-13 13:56:28 +00002824#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002825static void
Fred Drake509d79a2000-07-08 04:04:38 +00002826MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002827{
2828 stdin_ready = 1;
2829}
Guido van Rossumad4db171998-06-13 13:56:28 +00002830#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002831
Guido van Rossum00d93061998-05-28 23:06:38 +00002832static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002833
Guido van Rossum18468821994-06-20 07:49:28 +00002834static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002835EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002836{
Guido van Rossumad4db171998-06-13 13:56:28 +00002837#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002838 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002839#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002840#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002841 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002842#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002843 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002844 errorInCmd = 0;
2845#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002846 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002847 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002848#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002849 while (!errorInCmd && !stdin_ready) {
2850 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002851#ifdef MS_WINDOWS
2852 if (_kbhit()) {
2853 stdin_ready = 1;
2854 break;
2855 }
2856#endif
2857#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002858 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002859 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002860 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002861
Guido van Rossum00d93061998-05-28 23:06:38 +00002862 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002863
2864 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002865 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002866 if (result == 0)
2867 Sleep(20);
2868 Py_END_ALLOW_THREADS
2869#else
2870 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002871#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002872
2873 if (result < 0)
2874 break;
2875 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002876#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002877 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002878#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002879 if (errorInCmd) {
2880 errorInCmd = 0;
2881 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2882 excInCmd = valInCmd = trbInCmd = NULL;
2883 PyErr_Print();
2884 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002885#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002886 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002887#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002888 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002889}
Guido van Rossum18468821994-06-20 07:49:28 +00002890
Guido van Rossum00d93061998-05-28 23:06:38 +00002891#endif
2892
Guido van Rossum7bf15641998-05-22 18:28:17 +00002893static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002894EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002895{
Guido van Rossum00d93061998-05-28 23:06:38 +00002896#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002897 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002898#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002899 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002900#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002901 PyOS_InputHook = EventHook;
2902 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002903#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002904}
2905
2906static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002907DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002908{
Guido van Rossum00d93061998-05-28 23:06:38 +00002909#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002910 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2911 PyOS_InputHook = NULL;
2912 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002913#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002914}
2915
Barry Warsawfa701a81997-01-16 00:15:11 +00002916
2917/* all errors will be checked in one fell swoop in init_tkinter() */
2918static void
Fred Drake509d79a2000-07-08 04:04:38 +00002919ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002920{
2921 PyObject *v = PyInt_FromLong(val);
2922 if (v) {
2923 PyDict_SetItemString(d, name, v);
2924 Py_DECREF(v);
2925 }
2926}
2927static void
Fred Drake509d79a2000-07-08 04:04:38 +00002928ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002929{
2930 PyObject *v = PyString_FromString(val);
2931 if (v) {
2932 PyDict_SetItemString(d, name, v);
2933 Py_DECREF(v);
2934 }
2935}
2936
2937
Mark Hammond62b1ab12002-07-23 06:31:15 +00002938PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002939init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002940{
Barry Warsawfa701a81997-01-16 00:15:11 +00002941 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002942
Barry Warsawfa701a81997-01-16 00:15:11 +00002943 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002944
2945#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002946 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002947#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002948
Barry Warsawfa701a81997-01-16 00:15:11 +00002949 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002950
Barry Warsawfa701a81997-01-16 00:15:11 +00002951 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00002952 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00002953 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002954
Guido van Rossum35d43371997-08-02 00:09:09 +00002955 ins_long(d, "READABLE", TCL_READABLE);
2956 ins_long(d, "WRITABLE", TCL_WRITABLE);
2957 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2958 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2959 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2960 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2961 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2962 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2963 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002964 ins_string(d, "TK_VERSION", TK_VERSION);
2965 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002966
Guido van Rossum83551bf1997-09-13 00:44:23 +00002967 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002968
2969 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002970 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2971
Martin v. Löwisffad6332002-11-26 09:28:05 +00002972 PyTclObject_Type.ob_type = &PyType_Type;
2973 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002974
2975#ifdef TK_AQUA
2976 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2977 * start waking up. Note that Tcl_FindExecutable will do this, this
2978 * code must be above it! The original warning from
2979 * tkMacOSXAppInit.c is copied below.
2980 *
2981 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2982 * Tcl interpreter for now. It probably should work to do this
2983 * in the other order, but for now it doesn't seem to.
2984 *
2985 */
2986 Tk_MacOSXSetupTkNotifier();
2987#endif
2988
2989
Guido van Rossume187b0e2000-03-27 21:46:29 +00002990 /* This helps the dynamic loader; in Unicode aware Tcl versions
2991 it also helps Tcl find its encodings. */
2992 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00002993
Barry Warsawfa701a81997-01-16 00:15:11 +00002994 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002995 return;
2996
Guido van Rossum43ff8681998-07-14 18:02:13 +00002997#if 0
2998 /* This was not a good idea; through <Destroy> bindings,
2999 Tcl_Finalize() may invoke Python code but at that point the
3000 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003001 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003002#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003003
Jack Jansen34cc5c31995-10-31 16:15:12 +00003004#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003005 /*
3006 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
3007 ** Most of the initializations in that routine (toolbox init calls and
3008 ** such) have already been done for us, so we only need these.
3009 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003010 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003011
3012 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00003013#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00003014 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00003015#endif /* GENERATINGCFM */
3016#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00003017}
Guido van Rossum9722ad81995-09-22 23:49:28 +00003018
Guido van Rossumec22c921996-02-25 04:50:29 +00003019
Barry Warsawfa701a81997-01-16 00:15:11 +00003020
Guido van Rossum9722ad81995-09-22 23:49:28 +00003021#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003022
3023/*
Guido van Rossumec22c921996-02-25 04:50:29 +00003024** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003025*/
3026
Guido van Rossum9722ad81995-09-22 23:49:28 +00003027void
3028panic(char * format, ...)
3029{
Barry Warsawfa701a81997-01-16 00:15:11 +00003030 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003031
Barry Warsawfa701a81997-01-16 00:15:11 +00003032 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003033
Guido van Rossum227cf761998-08-05 13:53:32 +00003034 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00003035 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003036
Barry Warsawfa701a81997-01-16 00:15:11 +00003037 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003038
Barry Warsawfa701a81997-01-16 00:15:11 +00003039 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00003040}
Jack Jansen40b546d1995-11-14 10:34:45 +00003041
Guido van Rossumec22c921996-02-25 04:50:29 +00003042/*
3043** Pass events to SIOUX before passing them to Tk.
3044*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003045
Guido van Rossumec22c921996-02-25 04:50:29 +00003046static int
Fred Drake509d79a2000-07-08 04:04:38 +00003047PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003048{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003049 WindowPtr frontwin;
3050 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00003051 ** Sioux eats too many events, so we don't pass it everything. We
3052 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003053 ** the Sioux window is frontmost. This means that Tk menus don't work
3054 ** in that case, but at least we can scroll the sioux window.
3055 ** Note that the SIOUXIsAppWindow() routine we use here is not really
3056 ** part of the external interface of Sioux...
3057 */
3058 frontwin = FrontWindow();
3059 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
3060 if (SIOUXHandleOneEvent(eventPtr))
3061 return 0; /* Nothing happened to the Tcl event queue */
3062 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003063 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003064}
3065
Guido van Rossumec22c921996-02-25 04:50:29 +00003066#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003067
3068/*
3069** Additional Mac specific code for dealing with shared libraries.
3070*/
3071
3072#include <Resources.h>
3073#include <CodeFragments.h>
3074
3075static int loaded_from_shlib = 0;
3076static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003077
Jack Jansen34cc5c31995-10-31 16:15:12 +00003078/*
3079** If this module is dynamically loaded the following routine should
3080** be the init routine. It takes care of adding the shared library to
3081** the resource-file chain, so that the tk routines can find their
3082** resources.
3083*/
3084OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003085init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003086{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00003087 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00003088 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003089 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003090 library_fss = *data->fragLocator.u.onDisk.fileSpec;
3091 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003092 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003093 library_fss = *data->fragLocator.u.inSegs.fileSpec;
3094 loaded_from_shlib = 1;
3095 }
3096 return noErr;
3097}
3098
3099/*
3100** Insert the library resources into the search path. Put them after
3101** the resources from the application. Again, we ignore errors.
3102*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003103static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003104mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003105{
3106 if ( !loaded_from_shlib )
3107 return;
3108 (void)FSpOpenResFile(&library_fss, fsRdPerm);
3109}
3110
Guido van Rossumec22c921996-02-25 04:50:29 +00003111#endif /* GENERATINGCFM */
3112#endif /* macintosh */