blob: b9dc179eee3be14761dbf5a107ef7d8d67dab572 [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)
2053 return NULL;
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öwisb5bfb9f2002-12-12 17:07:58 +00002205 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002206 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002207 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002208 return NULL;
2209 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002210 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002211 return NULL;
2212 }
2213
Guido van Rossuma80649b2000-03-28 20:07:05 +00002214 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002215 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002216 return NULL;
2217
Barry Warsawfa701a81997-01-16 00:15:11 +00002218 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002219 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002220 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002221 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002222 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002223 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002224}
2225
2226static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002227Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002228{
Barry Warsawfa701a81997-01-16 00:15:11 +00002229 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002230 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002231
Guido van Rossum43713e52000-02-29 13:59:29 +00002232 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002233 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002234 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002235 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002236 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002237 return NULL;
2238
Guido van Rossuma80649b2000-03-28 20:07:05 +00002239 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002240
Barry Warsawfa701a81997-01-16 00:15:11 +00002241 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002242 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002243 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002244 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002245 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002246 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002247}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002248#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002249
Barry Warsawfa701a81997-01-16 00:15:11 +00002250
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002251/**** Tktt Object (timer token) ****/
2252
Jeremy Hylton938ace62002-07-17 16:30:39 +00002253static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002254
Guido van Rossum00d93061998-05-28 23:06:38 +00002255typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002256 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002257 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002258 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002259} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002260
2261static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002262Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002263{
Barry Warsawfa701a81997-01-16 00:15:11 +00002264 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002265 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002266
Guido van Rossum43713e52000-02-29 13:59:29 +00002267 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002268 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002269 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002270 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002271 v->token = NULL;
2272 }
2273 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002274 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002275 Py_DECREF(func);
2276 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002277 }
2278 Py_INCREF(Py_None);
2279 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002280}
2281
2282static PyMethodDef Tktt_methods[] =
2283{
Neal Norwitzb0493252002-03-31 14:44:22 +00002284 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002285 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002286};
2287
2288static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002289Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002290{
Barry Warsawfa701a81997-01-16 00:15:11 +00002291 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002292
Guido van Rossumb18618d2000-05-03 23:44:39 +00002293 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002294 if (v == NULL)
2295 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002296
Guido van Rossum00d93061998-05-28 23:06:38 +00002297 Py_INCREF(func);
2298 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002299 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002300
2301 /* Extra reference, deleted when called or when handler is deleted */
2302 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002303 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002304}
2305
2306static void
Fred Drake509d79a2000-07-08 04:04:38 +00002307Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002308{
Guido van Rossum00d93061998-05-28 23:06:38 +00002309 TkttObject *v = (TkttObject *)self;
2310 PyObject *func = v->func;
2311
2312 Py_XDECREF(func);
2313
Guido van Rossumb18618d2000-05-03 23:44:39 +00002314 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002315}
2316
Guido van Rossum597ac201998-05-12 14:36:19 +00002317static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002318Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002319{
Barry Warsawfa701a81997-01-16 00:15:11 +00002320 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002321 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002322
Tim Peters885d4572001-11-28 20:27:42 +00002323 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002324 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002325 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002326}
2327
2328static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002329Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002330{
Barry Warsawfa701a81997-01-16 00:15:11 +00002331 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002332}
2333
2334static PyTypeObject Tktt_Type =
2335{
Guido van Rossum35d43371997-08-02 00:09:09 +00002336 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002337 0, /*ob_size */
2338 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002339 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002340 0, /*tp_itemsize */
2341 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002342 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002343 Tktt_GetAttr, /*tp_getattr */
2344 0, /*tp_setattr */
2345 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002346 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002347 0, /*tp_as_number */
2348 0, /*tp_as_sequence */
2349 0, /*tp_as_mapping */
2350 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002351};
2352
Barry Warsawfa701a81997-01-16 00:15:11 +00002353
2354
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002355/** Timer Handler **/
2356
2357static void
Fred Drake509d79a2000-07-08 04:04:38 +00002358TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002359{
Guido van Rossum00d93061998-05-28 23:06:38 +00002360 TkttObject *v = (TkttObject *)clientData;
2361 PyObject *func = v->func;
2362 PyObject *res;
2363
2364 if (func == NULL)
2365 return;
2366
2367 v->func = NULL;
2368
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002369 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002370
2371 res = PyEval_CallObject(func, NULL);
2372 Py_DECREF(func);
2373 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002374
Barry Warsawfa701a81997-01-16 00:15:11 +00002375 if (res == NULL) {
2376 errorInCmd = 1;
2377 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2378 }
2379 else
2380 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002381
2382 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002383}
2384
2385static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002386Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002387{
Barry Warsawfa701a81997-01-16 00:15:11 +00002388 int milliseconds;
2389 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002390 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002391
Guido van Rossum2834b972000-10-06 16:58:26 +00002392 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2393 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002394 return NULL;
2395 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002396 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002397 return NULL;
2398 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002399 v = Tktt_New(func);
2400 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2401 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002402
Guido van Rossum00d93061998-05-28 23:06:38 +00002403 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002404}
2405
Barry Warsawfa701a81997-01-16 00:15:11 +00002406
Guido van Rossum18468821994-06-20 07:49:28 +00002407/** Event Loop **/
2408
Guido van Rossum18468821994-06-20 07:49:28 +00002409static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002410Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002411{
Barry Warsawfa701a81997-01-16 00:15:11 +00002412 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002413 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002414#ifdef WITH_THREAD
2415 PyThreadState *tstate = PyThreadState_Get();
2416#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002417
Guido van Rossum43713e52000-02-29 13:59:29 +00002418 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002419 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002420
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002421 if (!self && !tcl_lock) {
2422 /* We don't have the Tcl lock since Tcl is threaded. */
2423 PyErr_SetString(PyExc_RuntimeError,
2424 "_tkinter.mainloop not supported "
2425 "for threaded Tcl");
2426 return NULL;
2427 }
2428
2429 if (self) {
2430 CHECK_TCL_APPARTMENT;
2431 self->dispatching = 1;
2432 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002433
Barry Warsawfa701a81997-01-16 00:15:11 +00002434 quitMainLoop = 0;
2435 while (Tk_GetNumMainWindows() > threshold &&
2436 !quitMainLoop &&
2437 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002438 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002439 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002440
2441#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002442 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002443 /* Allow other Python threads to run. */
2444 ENTER_TCL
2445 result = Tcl_DoOneEvent(0);
2446 LEAVE_TCL
2447 }
2448 else {
2449 Py_BEGIN_ALLOW_THREADS
2450 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2451 tcl_tstate = tstate;
2452 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2453 tcl_tstate = NULL;
2454 if(tcl_lock)PyThread_release_lock(tcl_lock);
2455 if (result == 0)
2456 Sleep(20);
2457 Py_END_ALLOW_THREADS
2458 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002459#else
2460 result = Tcl_DoOneEvent(0);
2461#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002462
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002463 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002464 if (self)
2465 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002466 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002467 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002468 if (result < 0)
2469 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002470 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002471 if (self)
2472 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002473 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002474
Barry Warsawfa701a81997-01-16 00:15:11 +00002475 if (errorInCmd) {
2476 errorInCmd = 0;
2477 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2478 excInCmd = valInCmd = trbInCmd = NULL;
2479 return NULL;
2480 }
2481 Py_INCREF(Py_None);
2482 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002483}
2484
2485static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002486Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002487{
Guido van Rossum35d43371997-08-02 00:09:09 +00002488 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002489 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002490
Guido van Rossum43713e52000-02-29 13:59:29 +00002491 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002492 return NULL;
2493
Guido van Rossum00d93061998-05-28 23:06:38 +00002494 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002495 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002496 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002497 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002498}
2499
2500static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002501Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002502{
2503
Guido van Rossum43713e52000-02-29 13:59:29 +00002504 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002505 return NULL;
2506
2507 quitMainLoop = 1;
2508 Py_INCREF(Py_None);
2509 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002510}
2511
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002512static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002513Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002514{
2515
Guido van Rossum43713e52000-02-29 13:59:29 +00002516 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002517 return NULL;
2518
2519 return PyInt_FromLong((long)Tkapp_Interp(self));
2520}
2521
Barry Warsawfa701a81997-01-16 00:15:11 +00002522
Martin v. Löwisffad6332002-11-26 09:28:05 +00002523static PyObject *
2524Tkapp_WantObjects(PyObject *self, PyObject *args)
2525{
2526
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002527 int wantobjects;
2528 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002529 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002530 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002531
2532 Py_INCREF(Py_None);
2533 return Py_None;
2534}
2535
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002536static PyObject *
2537Tkapp_WillDispatch(PyObject *self, PyObject *args)
2538{
2539
2540 ((TkappObject*)self)->dispatching = 1;
2541
2542 Py_INCREF(Py_None);
2543 return Py_None;
2544}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002545
Barry Warsawfa701a81997-01-16 00:15:11 +00002546
Guido van Rossum18468821994-06-20 07:49:28 +00002547/**** Tkapp Method List ****/
2548
2549static PyMethodDef Tkapp_methods[] =
2550{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002551 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002552 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002553 {"call", Tkapp_Call, METH_OLDARGS},
2554 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2555 {"eval", Tkapp_Eval, METH_VARARGS},
2556 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2557 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2558 {"record", Tkapp_Record, METH_VARARGS},
2559 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2560 {"setvar", Tkapp_SetVar, METH_VARARGS},
2561 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2562 {"getvar", Tkapp_GetVar, METH_VARARGS},
2563 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2564 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2565 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2566 {"getint", Tkapp_GetInt, METH_VARARGS},
2567 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2568 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2569 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2570 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2571 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2572 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2573 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2574 {"split", Tkapp_Split, METH_VARARGS},
2575 {"merge", Tkapp_Merge, METH_OLDARGS},
2576 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2577 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002578#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002579 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2580 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002581#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002582 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2583 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2584 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2585 {"quit", Tkapp_Quit, METH_VARARGS},
2586 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002587 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002588};
2589
Barry Warsawfa701a81997-01-16 00:15:11 +00002590
2591
Guido van Rossum18468821994-06-20 07:49:28 +00002592/**** Tkapp Type Methods ****/
2593
2594static void
Fred Drake509d79a2000-07-08 04:04:38 +00002595Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002596{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002597 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002598 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002599 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002600 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002601 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002602 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002603}
2604
2605static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002606Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002607{
Guido van Rossum35d43371997-08-02 00:09:09 +00002608 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002609}
2610
2611static PyTypeObject Tkapp_Type =
2612{
Guido van Rossum35d43371997-08-02 00:09:09 +00002613 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002614 0, /*ob_size */
2615 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002616 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002617 0, /*tp_itemsize */
2618 Tkapp_Dealloc, /*tp_dealloc */
2619 0, /*tp_print */
2620 Tkapp_GetAttr, /*tp_getattr */
2621 0, /*tp_setattr */
2622 0, /*tp_compare */
2623 0, /*tp_repr */
2624 0, /*tp_as_number */
2625 0, /*tp_as_sequence */
2626 0, /*tp_as_mapping */
2627 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002628};
2629
Barry Warsawfa701a81997-01-16 00:15:11 +00002630
2631
Guido van Rossum18468821994-06-20 07:49:28 +00002632/**** Tkinter Module ****/
2633
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002634typedef struct {
2635 PyObject* tuple;
2636 int size; /* current size */
2637 int maxsize; /* allocated size */
2638} FlattenContext;
2639
2640static int
2641_bump(FlattenContext* context, int size)
2642{
Guido van Rossum2834b972000-10-06 16:58:26 +00002643 /* expand tuple to hold (at least) size new items.
2644 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002645
2646 int maxsize = context->maxsize * 2;
2647
2648 if (maxsize < context->size + size)
2649 maxsize = context->size + size;
2650
2651 context->maxsize = maxsize;
2652
Tim Peters4324aa32001-05-28 22:30:08 +00002653 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002654}
2655
2656static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002657_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002658{
2659 /* add tuple or list to argument tuple (recursively) */
2660
2661 int i, size;
2662
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002663 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002664 PyErr_SetString(PyExc_ValueError,
2665 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002666 return 0;
2667 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002668 size = PyList_GET_SIZE(item);
2669 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002670 if (context->size + size > context->maxsize &&
2671 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002672 return 0;
2673 /* copy items to output tuple */
2674 for (i = 0; i < size; i++) {
2675 PyObject *o = PyList_GET_ITEM(item, i);
2676 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002677 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002678 return 0;
2679 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002680 if (context->size + 1 > context->maxsize &&
2681 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002682 return 0;
2683 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002684 PyTuple_SET_ITEM(context->tuple,
2685 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002686 }
2687 }
2688 } else if (PyTuple_Check(item)) {
2689 /* same, for tuples */
2690 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002691 if (context->size + size > context->maxsize &&
2692 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002693 return 0;
2694 for (i = 0; i < size; i++) {
2695 PyObject *o = PyTuple_GET_ITEM(item, i);
2696 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002697 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002698 return 0;
2699 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002700 if (context->size + 1 > context->maxsize &&
2701 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002702 return 0;
2703 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002704 PyTuple_SET_ITEM(context->tuple,
2705 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002706 }
2707 }
2708 } else {
2709 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2710 return 0;
2711 }
2712 return 1;
2713}
2714
2715static PyObject *
2716Tkinter_Flatten(PyObject* self, PyObject* args)
2717{
2718 FlattenContext context;
2719 PyObject* item;
2720
2721 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2722 return NULL;
2723
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002724 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002725 if (context.maxsize <= 0)
2726 return PyTuple_New(0);
2727
2728 context.tuple = PyTuple_New(context.maxsize);
2729 if (!context.tuple)
2730 return NULL;
2731
2732 context.size = 0;
2733
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002734 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002735 return NULL;
2736
Tim Peters4324aa32001-05-28 22:30:08 +00002737 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002738 return NULL;
2739
2740 return context.tuple;
2741}
2742
Guido van Rossum18468821994-06-20 07:49:28 +00002743static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002744Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002745{
Barry Warsawfa701a81997-01-16 00:15:11 +00002746 char *screenName = NULL;
2747 char *baseName = NULL;
2748 char *className = NULL;
2749 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002750 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002751
Guido van Rossum35d43371997-08-02 00:09:09 +00002752 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002753 if (baseName != NULL)
2754 baseName++;
2755 else
2756 baseName = Py_GetProgramName();
2757 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002758
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002759 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002760 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002761 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002762 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002763
Barry Warsawfa701a81997-01-16 00:15:11 +00002764 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002765 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002766}
2767
2768static PyMethodDef moduleMethods[] =
2769{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002770 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2771 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002772#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002773 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2774 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002775#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002776 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2777 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2778 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2779 {"quit", Tkapp_Quit, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002780 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002781};
2782
Guido van Rossum7bf15641998-05-22 18:28:17 +00002783#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002784
2785static int stdin_ready = 0;
2786
Guido van Rossumad4db171998-06-13 13:56:28 +00002787#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002788static void
Fred Drake509d79a2000-07-08 04:04:38 +00002789MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002790{
2791 stdin_ready = 1;
2792}
Guido van Rossumad4db171998-06-13 13:56:28 +00002793#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002794
Guido van Rossum00d93061998-05-28 23:06:38 +00002795static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002796
Guido van Rossum18468821994-06-20 07:49:28 +00002797static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002798EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002799{
Guido van Rossumad4db171998-06-13 13:56:28 +00002800#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002801 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002802#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002803#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002804 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002805#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002806 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002807 errorInCmd = 0;
2808#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002809 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002810 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002811#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002812 while (!errorInCmd && !stdin_ready) {
2813 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002814#ifdef MS_WINDOWS
2815 if (_kbhit()) {
2816 stdin_ready = 1;
2817 break;
2818 }
2819#endif
2820#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002821 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002822 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002823 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002824
Guido van Rossum00d93061998-05-28 23:06:38 +00002825 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002826
2827 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002828 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002829 if (result == 0)
2830 Sleep(20);
2831 Py_END_ALLOW_THREADS
2832#else
2833 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002834#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002835
2836 if (result < 0)
2837 break;
2838 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002839#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002840 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002841#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002842 if (errorInCmd) {
2843 errorInCmd = 0;
2844 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2845 excInCmd = valInCmd = trbInCmd = NULL;
2846 PyErr_Print();
2847 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002848#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002849 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002850#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002851 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002852}
Guido van Rossum18468821994-06-20 07:49:28 +00002853
Guido van Rossum00d93061998-05-28 23:06:38 +00002854#endif
2855
Guido van Rossum7bf15641998-05-22 18:28:17 +00002856static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002857EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002858{
Guido van Rossum00d93061998-05-28 23:06:38 +00002859#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002860 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002861#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002862 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002863#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002864 PyOS_InputHook = EventHook;
2865 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002866#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002867}
2868
2869static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002870DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002871{
Guido van Rossum00d93061998-05-28 23:06:38 +00002872#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002873 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2874 PyOS_InputHook = NULL;
2875 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002876#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002877}
2878
Barry Warsawfa701a81997-01-16 00:15:11 +00002879
2880/* all errors will be checked in one fell swoop in init_tkinter() */
2881static void
Fred Drake509d79a2000-07-08 04:04:38 +00002882ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002883{
2884 PyObject *v = PyInt_FromLong(val);
2885 if (v) {
2886 PyDict_SetItemString(d, name, v);
2887 Py_DECREF(v);
2888 }
2889}
2890static void
Fred Drake509d79a2000-07-08 04:04:38 +00002891ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002892{
2893 PyObject *v = PyString_FromString(val);
2894 if (v) {
2895 PyDict_SetItemString(d, name, v);
2896 Py_DECREF(v);
2897 }
2898}
2899
2900
Mark Hammond62b1ab12002-07-23 06:31:15 +00002901PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002902init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002903{
Barry Warsawfa701a81997-01-16 00:15:11 +00002904 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002905
Barry Warsawfa701a81997-01-16 00:15:11 +00002906 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002907
2908#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002909 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002910#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002911
Barry Warsawfa701a81997-01-16 00:15:11 +00002912 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002913
Barry Warsawfa701a81997-01-16 00:15:11 +00002914 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00002915 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00002916 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002917
Guido van Rossum35d43371997-08-02 00:09:09 +00002918 ins_long(d, "READABLE", TCL_READABLE);
2919 ins_long(d, "WRITABLE", TCL_WRITABLE);
2920 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2921 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2922 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2923 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2924 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2925 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2926 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002927 ins_string(d, "TK_VERSION", TK_VERSION);
2928 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002929
Guido van Rossum83551bf1997-09-13 00:44:23 +00002930 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002931
2932 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002933 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2934
Martin v. Löwisffad6332002-11-26 09:28:05 +00002935 PyTclObject_Type.ob_type = &PyType_Type;
2936 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002937
2938#ifdef TK_AQUA
2939 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2940 * start waking up. Note that Tcl_FindExecutable will do this, this
2941 * code must be above it! The original warning from
2942 * tkMacOSXAppInit.c is copied below.
2943 *
2944 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2945 * Tcl interpreter for now. It probably should work to do this
2946 * in the other order, but for now it doesn't seem to.
2947 *
2948 */
2949 Tk_MacOSXSetupTkNotifier();
2950#endif
2951
2952
Guido van Rossume187b0e2000-03-27 21:46:29 +00002953 /* This helps the dynamic loader; in Unicode aware Tcl versions
2954 it also helps Tcl find its encodings. */
2955 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00002956
Barry Warsawfa701a81997-01-16 00:15:11 +00002957 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002958 return;
2959
Guido van Rossum43ff8681998-07-14 18:02:13 +00002960#if 0
2961 /* This was not a good idea; through <Destroy> bindings,
2962 Tcl_Finalize() may invoke Python code but at that point the
2963 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002964 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002965#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002966
Jack Jansen34cc5c31995-10-31 16:15:12 +00002967#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002968 /*
2969 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2970 ** Most of the initializations in that routine (toolbox init calls and
2971 ** such) have already been done for us, so we only need these.
2972 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002973 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002974
2975 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00002976#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00002977 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00002978#endif /* GENERATINGCFM */
2979#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00002980}
Guido van Rossum9722ad81995-09-22 23:49:28 +00002981
Guido van Rossumec22c921996-02-25 04:50:29 +00002982
Barry Warsawfa701a81997-01-16 00:15:11 +00002983
Guido van Rossum9722ad81995-09-22 23:49:28 +00002984#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002985
2986/*
Guido van Rossumec22c921996-02-25 04:50:29 +00002987** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002988*/
2989
Guido van Rossum9722ad81995-09-22 23:49:28 +00002990void
2991panic(char * format, ...)
2992{
Barry Warsawfa701a81997-01-16 00:15:11 +00002993 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002994
Barry Warsawfa701a81997-01-16 00:15:11 +00002995 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002996
Guido van Rossum227cf761998-08-05 13:53:32 +00002997 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002998 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002999
Barry Warsawfa701a81997-01-16 00:15:11 +00003000 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003001
Barry Warsawfa701a81997-01-16 00:15:11 +00003002 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00003003}
Jack Jansen40b546d1995-11-14 10:34:45 +00003004
Guido van Rossumec22c921996-02-25 04:50:29 +00003005/*
3006** Pass events to SIOUX before passing them to Tk.
3007*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003008
Guido van Rossumec22c921996-02-25 04:50:29 +00003009static int
Fred Drake509d79a2000-07-08 04:04:38 +00003010PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003011{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003012 WindowPtr frontwin;
3013 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00003014 ** Sioux eats too many events, so we don't pass it everything. We
3015 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003016 ** the Sioux window is frontmost. This means that Tk menus don't work
3017 ** in that case, but at least we can scroll the sioux window.
3018 ** Note that the SIOUXIsAppWindow() routine we use here is not really
3019 ** part of the external interface of Sioux...
3020 */
3021 frontwin = FrontWindow();
3022 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
3023 if (SIOUXHandleOneEvent(eventPtr))
3024 return 0; /* Nothing happened to the Tcl event queue */
3025 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003026 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003027}
3028
Guido van Rossumec22c921996-02-25 04:50:29 +00003029#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003030
3031/*
3032** Additional Mac specific code for dealing with shared libraries.
3033*/
3034
3035#include <Resources.h>
3036#include <CodeFragments.h>
3037
3038static int loaded_from_shlib = 0;
3039static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003040
Jack Jansen34cc5c31995-10-31 16:15:12 +00003041/*
3042** If this module is dynamically loaded the following routine should
3043** be the init routine. It takes care of adding the shared library to
3044** the resource-file chain, so that the tk routines can find their
3045** resources.
3046*/
3047OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003048init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003049{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00003050 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00003051 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003052 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003053 library_fss = *data->fragLocator.u.onDisk.fileSpec;
3054 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003055 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003056 library_fss = *data->fragLocator.u.inSegs.fileSpec;
3057 loaded_from_shlib = 1;
3058 }
3059 return noErr;
3060}
3061
3062/*
3063** Insert the library resources into the search path. Put them after
3064** the resources from the application. Again, we ignore errors.
3065*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003066static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003067mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003068{
3069 if ( !loaded_from_shlib )
3070 return;
3071 (void)FSpOpenResFile(&library_fss, fsRdPerm);
3072}
3073
Guido van Rossumec22c921996-02-25 04:50:29 +00003074#endif /* GENERATINGCFM */
3075#endif /* macintosh */