blob: c759a3a6f7f88b00ae715cde10f585debd471565 [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
42#define PyDoc_STRVAR(name,str) static char name[] = PyDoc_STR(str)
43#endif
44
45#ifndef PyMODINIT_FUNC
46#define PyPyMODINIT_FUNC void
47#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 Tishlerbbe89612002-12-31 20:30:46 +0000837 0, /*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));
871 else if (PyInt_Check(value))
872 return Tcl_NewLongObj(PyInt_AS_LONG(value));
873 else if (PyFloat_Check(value))
874 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
875 else if (PyTuple_Check(value)) {
876 Tcl_Obj **argv = (Tcl_Obj**)
877 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
878 int i;
879 if(!argv)
880 return 0;
881 for(i=0;i<PyTuple_Size(value);i++)
882 argv[i] = AsObj(PyTuple_GetItem(value,i));
883 result = Tcl_NewListObj(PyTuple_Size(value), argv);
884 ckfree(FREECAST argv);
885 return result;
886 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000887#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000888 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000889 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
890 int size = PyUnicode_GET_SIZE(value);
891 /* This #ifdef assumes that Tcl uses UCS-2.
892 See TCL_UTF_MAX test above. */
893#ifdef Py_UNICODE_WIDE
894 Tcl_UniChar *outbuf;
895 int i;
896 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
897 if (!outbuf) {
898 PyErr_NoMemory();
899 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000900 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000901 for (i = 0; i < size; i++) {
902 if (inbuf[i] >= 0x10000) {
903 /* Tcl doesn't do UTF-16, yet. */
904 PyErr_SetString(PyExc_ValueError,
905 "unsupported character");
906 ckfree(FREECAST outbuf);
907 return NULL;
908 }
909 outbuf[i] = inbuf[i];
910 }
911 result = Tcl_NewUnicodeObj(outbuf, size);
912 ckfree(FREECAST outbuf);
913 return result;
914#else
915 return Tcl_NewUnicodeObj(inbuf, size);
916#endif
917
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000918 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000919#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000920 else if(PyTclObject_Check(value)) {
921 Tcl_Obj *v = ((PyTclObject*)value)->value;
922 Tcl_IncrRefCount(v);
923 return v;
924 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000925 else {
926 PyObject *v = PyObject_Str(value);
927 if (!v)
928 return 0;
929 result = AsObj(v);
930 Py_DECREF(v);
931 return result;
932 }
933}
934
Martin v. Löwisffad6332002-11-26 09:28:05 +0000935static PyObject*
936FromObj(PyObject* tkapp, Tcl_Obj *value)
937{
938 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000939 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000940
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000941 if (value->typePtr == NULL) {
942 /* If the result contains any bytes with the top bit set,
943 it's UTF-8 and we should decode it to Unicode */
944#ifdef Py_USING_UNICODE
945 int i;
946 char *s = value->bytes;
947 int len = value->length;
948 for (i = 0; i < len; i++) {
949 if (value->bytes[i] & 0x80)
950 break;
951 }
952
953 if (i == value->length)
954 result = PyString_FromStringAndSize(s, len);
955 else {
956 /* Convert UTF-8 to Unicode string */
957 result = PyUnicode_DecodeUTF8(s, len, "strict");
958 if (result == NULL) {
959 PyErr_Clear();
960 result = PyString_FromStringAndSize(s, len);
961 }
962 }
963#else
964 res = PyString_FromStringAndSize(value->bytes, value->length);
965#endif
966 return result;
967 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000968
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000969 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000970 result = value->internalRep.longValue ? Py_True : Py_False;
971 Py_INCREF(result);
972 return result;
973 }
974
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000975 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000976 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000977 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000978 return PyString_FromStringAndSize(data, size);
979 }
980
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000981 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000982 return PyFloat_FromDouble(value->internalRep.doubleValue);
983 }
984
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000985 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000986 return PyInt_FromLong(value->internalRep.longValue);
987 }
988
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000989 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000990 int size;
991 int i, status;
992 PyObject *elem;
993 Tcl_Obj *tcl_elem;
994
995 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
996 if (status == TCL_ERROR)
997 return Tkinter_Error(tkapp);
998 result = PyTuple_New(size);
999 if (!result)
1000 return NULL;
1001 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001002 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001003 value, i, &tcl_elem);
1004 if (status == TCL_ERROR) {
1005 Py_DECREF(result);
1006 return Tkinter_Error(tkapp);
1007 }
1008 elem = FromObj(tkapp, tcl_elem);
1009 if (!elem) {
1010 Py_DECREF(result);
1011 return NULL;
1012 }
1013 PyTuple_SetItem(result, i, elem);
1014 }
1015 return result;
1016 }
1017
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001018 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001019 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001020 }
1021
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001022 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001023#ifdef Py_USING_UNICODE
1024#ifdef Py_UNICODE_WIDE
1025 PyObject *result;
1026 int size;
1027 Tcl_UniChar *input;
1028 Py_UNICODE *output;
1029
1030 size = Tcl_GetCharLength(value);
1031 result = PyUnicode_FromUnicode(NULL, size);
1032 if (!result)
1033 return NULL;
1034 input = Tcl_GetUnicode(value);
1035 output = PyUnicode_AS_UNICODE(result);
1036 while (size--)
1037 *output++ = *input++;
1038 return result;
1039#else
1040 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1041 Tcl_GetCharLength(value));
1042#endif
1043#else
1044 int size;
1045 char *c;
1046 c = Tcl_GetStringFromObj(value, &size);
1047 return PyString_FromStringAndSize(c, size);
1048#endif
1049 }
1050
1051 return newPyTclObject(value);
1052}
1053
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001054/* This mutex synchronizes inter-thread command calls. */
1055
1056TCL_DECLARE_MUTEX(call_mutex)
1057
1058typedef struct Tkapp_CallEvent {
1059 Tcl_Event ev; /* Must be first */
1060 TkappObject *self;
1061 PyObject *args;
1062 int flags;
1063 PyObject **res;
1064 PyObject **exc_type, **exc_value, **exc_tb;
1065 Tcl_Condition done;
1066} Tkapp_CallEvent;
1067
1068void
1069Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001070{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001071 int i;
1072 for (i = 0; i < objc; i++)
1073 Tcl_DecrRefCount(objv[i]);
1074 if (objv != objStore)
1075 ckfree(FREECAST objv);
1076}
Guido van Rossum18468821994-06-20 07:49:28 +00001077
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001078/* Convert Python objects to Tcl objects. This must happen in the
1079 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001080
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001081static Tcl_Obj**
1082Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1083{
1084 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001085 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001086 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001087 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001088
Guido van Rossum212643f1998-04-29 16:22:14 +00001089 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001090 objv[0] = AsObj(args);
1091 if (objv[0] == 0)
1092 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001093 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001094 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001095 }
1096 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001097 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001098
Guido van Rossum632de272000-03-29 00:19:50 +00001099 if (objc > ARGSZ) {
1100 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1101 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001102 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001103 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001104 goto finally;
1105 }
1106 }
1107
Guido van Rossum632de272000-03-29 00:19:50 +00001108 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001109 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001110 if (v == Py_None) {
1111 objc = i;
1112 break;
1113 }
Guido van Rossum632de272000-03-29 00:19:50 +00001114 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001115 if (!objv[i]) {
1116 /* Reset objc, so it attempts to clear
1117 objects only up to i. */
1118 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001119 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001120 }
Guido van Rossum632de272000-03-29 00:19:50 +00001121 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001122 }
1123 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001124 *pobjc = objc;
1125 return objv;
1126finally:
1127 Tkapp_CallDeallocArgs(objv, objStore, objc);
1128 return NULL;
1129}
Guido van Rossum212643f1998-04-29 16:22:14 +00001130
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001131/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001132
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001133static PyObject*
1134Tkapp_CallResult(TkappObject *self)
1135{
1136 PyObject *res = NULL;
1137 if(self->wantobjects) {
1138 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001139 /* Not sure whether the IncrRef is necessary, but something
1140 may overwrite the interpreter result while we are
1141 converting it. */
1142 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001143 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001144 Tcl_DecrRefCount(value);
1145 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001146 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001147 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001148
Guido van Rossum990f5c62000-05-04 15:07:16 +00001149 /* If the result contains any bytes with the top bit set,
1150 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001151#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001152 while (*p != '\0') {
1153 if (*p & 0x80)
1154 break;
1155 p++;
1156 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001157
Guido van Rossum990f5c62000-05-04 15:07:16 +00001158 if (*p == '\0')
1159 res = PyString_FromStringAndSize(s, (int)(p-s));
1160 else {
1161 /* Convert UTF-8 to Unicode string */
1162 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001163 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1164 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001165 PyErr_Clear();
1166 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001167 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001168 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001169#else
1170 p = strchr(p, '\0');
1171 res = PyString_FromStringAndSize(s, (int)(p-s));
1172#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001173 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001174 return res;
1175}
Guido van Rossum632de272000-03-29 00:19:50 +00001176
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001177/* Tkapp_CallProc is the event procedure that is executed in the context of
1178 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1179 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001180
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001181static int
1182Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1183{
1184 Tcl_Obj *objStore[ARGSZ];
1185 Tcl_Obj **objv;
1186 int objc;
1187 int i;
1188 ENTER_PYTHON
1189 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1190 if (!objv) {
1191 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1192 *(e->res) = NULL;
1193 }
1194 LEAVE_PYTHON
1195 if (!objv)
1196 goto done;
1197 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1198 ENTER_PYTHON
1199 if (i == TCL_ERROR) {
1200 *(e->res) = NULL;
1201 *(e->exc_type) = NULL;
1202 *(e->exc_tb) = NULL;
1203 *(e->exc_value) = PyObject_CallFunction(
1204 Tkinter_TclError, "s",
1205 Tcl_GetStringResult(e->self->interp));
1206 }
1207 else {
1208 *(e->res) = Tkapp_CallResult(e->self);
1209 }
1210 LEAVE_PYTHON
1211 done:
1212 /* Wake up calling thread. */
1213 Tcl_MutexLock(&call_mutex);
1214 Tcl_ConditionNotify(&e->done);
1215 Tcl_MutexUnlock(&call_mutex);
1216 return 1;
1217}
1218
1219/* This is the main entry point for calling a Tcl command.
1220 It supports three cases, with regard to threading:
1221 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1222 the context of the calling thread.
1223 2. Tcl is threaded, caller of the command is in the interpreter thread:
1224 Execute the command in the calling thread. Since the Tcl lock will
1225 not be used, we can merge that with case 1.
1226 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1227 the interpreter thread. Allocation of Tcl objects needs to occur in the
1228 interpreter thread, so we ship the PyObject* args to the target thread,
1229 and perform processing there. */
1230
1231static PyObject *
1232Tkapp_Call(PyObject *_self, PyObject *args)
1233{
1234 Tcl_Obj *objStore[ARGSZ];
1235 Tcl_Obj **objv = NULL;
1236 int objc, i;
1237 PyObject *res = NULL;
1238 TkappObject *self = (TkappObject*)_self;
1239 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1240 int flags = TCL_EVAL_DIRECT;
1241
1242 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1243 /* We cannot call the command directly. Instead, we must
1244 marshal the parameters to the interpreter thread. */
1245 Tkapp_CallEvent *ev;
1246 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001247 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001248 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001249 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1250 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1251 ev->self = self;
1252 ev->args = args;
1253 ev->res = &res;
1254 ev->exc_type = &exc_type;
1255 ev->exc_value = &exc_value;
1256 ev->exc_tb = &exc_tb;
1257 ev->done = (Tcl_Condition)0;
1258
1259 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1260
1261 if (res == NULL) {
1262 if (exc_type)
1263 PyErr_Restore(exc_type, exc_value, exc_tb);
1264 else
1265 PyErr_SetObject(Tkinter_TclError, exc_value);
1266 }
1267 }
1268 else {
1269
1270 objv = Tkapp_CallArgs(args, objStore, &objc);
1271 if (!objv)
1272 return NULL;
1273
1274 ENTER_TCL
1275
1276 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1277
1278 ENTER_OVERLAP
1279
1280 if (i == TCL_ERROR)
1281 Tkinter_Error(_self);
1282 else
1283 res = Tkapp_CallResult(self);
1284
1285 LEAVE_OVERLAP_TCL
1286
1287 Tkapp_CallDeallocArgs(objv, objStore, objc);
1288 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001289 return res;
1290}
1291
1292
1293static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001294Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001295{
Guido van Rossum212643f1998-04-29 16:22:14 +00001296 /* Could do the same here as for Tkapp_Call(), but this is not used
1297 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1298 way for the user to do what all its Global* variants do (save and
1299 reset the scope pointer, call the local version, restore the saved
1300 scope pointer). */
1301
Guido van Rossum62320c91998-06-15 04:36:09 +00001302 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001303 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001304
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001305 CHECK_TCL_APPARTMENT;
1306
Guido van Rossum62320c91998-06-15 04:36:09 +00001307 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001308 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001309 int err;
1310 ENTER_TCL
1311 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001312 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001313 if (err == TCL_ERROR)
1314 res = Tkinter_Error(self);
1315 else
1316 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001317 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001318 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001319 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001320
1321 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001322}
1323
1324static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001325Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001326{
Barry Warsawfa701a81997-01-16 00:15:11 +00001327 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001328 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001329 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001330
Guido van Rossum43713e52000-02-29 13:59:29 +00001331 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001332 return NULL;
1333
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001334 CHECK_TCL_APPARTMENT;
1335
Guido van Rossum00d93061998-05-28 23:06:38 +00001336 ENTER_TCL
1337 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001338 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001339 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001340 res = Tkinter_Error(self);
1341 else
1342 res = PyString_FromString(Tkapp_Result(self));
1343 LEAVE_OVERLAP_TCL
1344 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001345}
1346
1347static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001348Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001349{
Barry Warsawfa701a81997-01-16 00:15:11 +00001350 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001351 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001352 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001353
Guido van Rossum43713e52000-02-29 13:59:29 +00001354 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001355 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001356
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001357 CHECK_TCL_APPARTMENT;
1358
Guido van Rossum00d93061998-05-28 23:06:38 +00001359 ENTER_TCL
1360 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001361 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001362 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001363 res = Tkinter_Error(self);
1364 else
1365 res = PyString_FromString(Tkapp_Result(self));
1366 LEAVE_OVERLAP_TCL
1367 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001368}
1369
1370static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001371Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001372{
Barry Warsawfa701a81997-01-16 00:15:11 +00001373 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001374 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001375 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001376
Guido van Rossum43713e52000-02-29 13:59:29 +00001377 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001378 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001379
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001380 CHECK_TCL_APPARTMENT;
1381
Guido van Rossum00d93061998-05-28 23:06:38 +00001382 ENTER_TCL
1383 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001384 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001385 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001386 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001387
Guido van Rossum62320c91998-06-15 04:36:09 +00001388 else
1389 res = PyString_FromString(Tkapp_Result(self));
1390 LEAVE_OVERLAP_TCL
1391 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001392}
1393
1394static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001395Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001396{
Barry Warsawfa701a81997-01-16 00:15:11 +00001397 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001398 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001399 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001400
Guido van Rossum35d43371997-08-02 00:09:09 +00001401 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001402 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001403
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001404 CHECK_TCL_APPARTMENT;
1405
Guido van Rossum00d93061998-05-28 23:06:38 +00001406 ENTER_TCL
1407 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001408 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001409 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001410 res = Tkinter_Error(self);
1411 else
1412 res = PyString_FromString(Tkapp_Result(self));
1413 LEAVE_OVERLAP_TCL
1414 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001415}
1416
1417static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001418Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001419{
Barry Warsawfa701a81997-01-16 00:15:11 +00001420 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001421
Guido van Rossum43713e52000-02-29 13:59:29 +00001422 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001423 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001424 CHECK_TCL_APPARTMENT;
1425
Guido van Rossum00d93061998-05-28 23:06:38 +00001426 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001427 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001428 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001429
Barry Warsawfa701a81997-01-16 00:15:11 +00001430 Py_INCREF(Py_None);
1431 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001432}
1433
Barry Warsawfa701a81997-01-16 00:15:11 +00001434
1435
Guido van Rossum18468821994-06-20 07:49:28 +00001436/** Tcl Variable **/
1437
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001438TCL_DECLARE_MUTEX(var_mutex)
1439
Martin v. Löwis5b177f12002-12-30 18:14:15 +00001440typedef CONST84_RETURN char* (*EventFunc1)(Tcl_Interp*, CONST char*, int);
1441typedef CONST84_RETURN char* (*EventFunc2)(Tcl_Interp*, CONST char*, CONST char*, int);
1442typedef CONST84_RETURN char* (*EventFunc3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001443typedef struct VarEvent {
1444 Tcl_Event ev; /* must be first */
1445 TkappObject *self;
1446 char* arg1;
1447 char* arg2;
1448 char* arg3;
1449 int flags;
1450 EventFunc1 func1;
1451 EventFunc2 func2;
1452 EventFunc3 func3;
1453 PyObject **res;
1454 PyObject **exc;
1455 Tcl_Condition cond;
1456 int coderesult;
1457} VarEvent;
1458
1459static const char*
1460var_perform(VarEvent *ev)
1461{
1462 if (!ev->arg2 && !ev->arg2)
1463 return ev->func1(ev->self->interp, ev->arg1, ev->flags);
1464 if (!ev->arg3)
1465 return ev->func2(ev->self->interp, ev->arg1,
1466 ev->arg2, ev->flags);
1467 return ev->func3(ev->self->interp, ev->arg1, ev->arg2,
1468 ev->arg3, ev->flags);
1469}
1470
1471static void
1472var_fill_result(VarEvent *ev, const char* res)
1473{
1474 if (ev->coderesult) {
1475 if ((int)res != TCL_ERROR) {
1476 Py_INCREF(Py_None);
1477 *(ev->res) = Py_None;
1478 return;
1479 }
1480 }
1481 else if (res) {
1482 *(ev->res) = PyString_FromString(res);
1483 return;
1484 }
1485
1486 *(ev->res) = NULL;
1487 *(ev->exc) = PyObject_CallFunction(
1488 Tkinter_TclError, "s",
1489 Tcl_GetStringResult(ev->self->interp));
1490
1491}
1492
1493static int
1494var_proc(VarEvent* ev, int flags)
1495{
1496 const char *result = var_perform(ev);
1497 ENTER_PYTHON
1498 var_fill_result(ev, result);
1499 Tcl_MutexLock(&var_mutex);
1500 Tcl_ConditionNotify(&ev->cond);
1501 Tcl_MutexUnlock(&var_mutex);
1502 LEAVE_PYTHON
1503 return 1;
1504}
1505
1506static PyObject*
1507var_invoke(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
1508 EventFunc1 func1, EventFunc2 func2, EventFunc3 func3,
1509 int coderesult)
1510{
1511 VarEvent _ev;
1512 TkappObject *self = (TkappObject*)_self;
1513 VarEvent *ev = self->threaded ?
1514 (VarEvent*)ckalloc(sizeof(VarEvent)) : &_ev;
1515 PyObject *res, *exc;
1516
1517 ev->self = self;
1518 ev->arg1 = arg1;
1519 ev->arg2 = arg2;
1520 ev->arg3 = arg3;
1521 ev->flags = flags;
1522 ev->func1 = func1;
1523 ev->func2 = func2;
1524 ev->func3 = func3;
1525 ev->coderesult = coderesult;
1526 ev->res = &res;
1527 ev->exc = &exc;
1528 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1529 /* The current thread is not the interpreter thread. Marshal
1530 the call to the interpreter thread, then wait for
1531 completion. */
1532
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001533 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001534 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001535 ev->cond = NULL;
1536 ev->ev.proc = (Tcl_EventProc*)var_proc;
1537 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1538 }
1539 else {
1540 /* Tcl is not threaded, or this is the interpreter thread. To
1541 perform the call, we must hold the TCL lock. To receive the
1542 results, we must also hold the Python lock. */
1543 const char *result;
1544 ENTER_TCL
1545 result = var_perform(ev);
1546 ENTER_OVERLAP
1547 var_fill_result(ev, result);
1548 LEAVE_OVERLAP_TCL
1549 }
1550 if (!res) {
1551 PyErr_SetObject(Tkinter_TclError, exc);
1552 return NULL;
1553 }
1554 return res;
1555}
1556
1557static PyObject*
1558var_invoke2(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
Martin v. Löwis5b177f12002-12-30 18:14:15 +00001559 int (*func1)(Tcl_Interp*, CONST char*, int),
1560 int (*func2)(Tcl_Interp*, CONST char*, CONST char*, int),
1561 int (*func3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001562{
1563 return var_invoke(_self, arg1, arg2, arg3, flags,
1564 (EventFunc1)func1, (EventFunc2)func2,
1565 (EventFunc3)func3, 1);
1566}
1567
Guido van Rossum18468821994-06-20 07:49:28 +00001568static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001569SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001570{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001571 char *name1, *name2, *s;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001572 PyObject *res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001573 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +00001574 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +00001575
Guido van Rossum62320c91998-06-15 04:36:09 +00001576 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +00001577 if (!tmp)
1578 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001579
Guido van Rossum43713e52000-02-29 13:59:29 +00001580 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001581 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +00001582 s = AsString(newValue, tmp);
Guido van Rossum2834b972000-10-06 16:58:26 +00001583 if (s == NULL)
1584 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001585 res = var_invoke(self, name1, s, NULL, flags,
1586 NULL, Tcl_SetVar, NULL, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001587 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001588 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001589 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001590 if (PyArg_ParseTuple(args, "ssO:setvar",
1591 &name1, &name2, &newValue)) {
1592 s = AsString(newValue, tmp);
1593 if (s == NULL)
1594 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001595 res = var_invoke(self, name1, name2, s, flags,
1596 NULL, NULL, Tcl_SetVar2, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001597 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001598 else {
Guido van Rossum00d93061998-05-28 23:06:38 +00001599 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +00001600 return NULL;
1601 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001602 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001603 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +00001604
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001605 if (!res)
1606 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001607
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001608 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001609 Py_INCREF(Py_None);
1610 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001611}
1612
1613static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001614Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001615{
Barry Warsawfa701a81997-01-16 00:15:11 +00001616 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001617}
1618
1619static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001620Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001621{
Barry Warsawfa701a81997-01-16 00:15:11 +00001622 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001623}
1624
Barry Warsawfa701a81997-01-16 00:15:11 +00001625
1626
Guido van Rossum18468821994-06-20 07:49:28 +00001627static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001628GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001629{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001630 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001631 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001632
Guido van Rossum43713e52000-02-29 13:59:29 +00001633 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001634 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001635
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001636 res = var_invoke(self, name1, name2, NULL, flags,
1637 Tcl_GetVar, Tcl_GetVar2, NULL, 0);
Guido van Rossum62320c91998-06-15 04:36:09 +00001638 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001639}
1640
1641static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001642Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001643{
Barry Warsawfa701a81997-01-16 00:15:11 +00001644 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001645}
1646
1647static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001648Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001649{
Barry Warsawfa701a81997-01-16 00:15:11 +00001650 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001651}
1652
Barry Warsawfa701a81997-01-16 00:15:11 +00001653
1654
Guido van Rossum18468821994-06-20 07:49:28 +00001655static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001656UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001657{
Guido van Rossum35d43371997-08-02 00:09:09 +00001658 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001659 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001660
Guido van Rossum43713e52000-02-29 13:59:29 +00001661 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001662 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001663
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001664 res = var_invoke2(self, name1, name2, NULL, flags,
1665 Tcl_UnsetVar, Tcl_UnsetVar2, NULL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001666 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001667}
1668
1669static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001670Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001671{
Barry Warsawfa701a81997-01-16 00:15:11 +00001672 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001673}
1674
1675static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001676Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001677{
Barry Warsawfa701a81997-01-16 00:15:11 +00001678 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001679}
1680
Barry Warsawfa701a81997-01-16 00:15:11 +00001681
1682
Guido van Rossum18468821994-06-20 07:49:28 +00001683/** Tcl to Python **/
1684
1685static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001686Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001687{
Barry Warsawfa701a81997-01-16 00:15:11 +00001688 char *s;
1689 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001690
Martin v. Löwisffad6332002-11-26 09:28:05 +00001691 if (PyTuple_Size(args) == 1) {
1692 PyObject* o = PyTuple_GetItem(args, 0);
1693 if (PyInt_Check(o)) {
1694 Py_INCREF(o);
1695 return o;
1696 }
1697 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001698 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001699 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001700 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001701 return Tkinter_Error(self);
1702 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001703}
1704
1705static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001706Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001707{
Barry Warsawfa701a81997-01-16 00:15:11 +00001708 char *s;
1709 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001710
Martin v. Löwisffad6332002-11-26 09:28:05 +00001711 if (PyTuple_Size(args) == 1) {
1712 PyObject *o = PyTuple_GetItem(args, 0);
1713 if (PyFloat_Check(o)) {
1714 Py_INCREF(o);
1715 return o;
1716 }
1717 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001718 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001719 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001720 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001721 return Tkinter_Error(self);
1722 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001723}
1724
1725static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001726Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001727{
Barry Warsawfa701a81997-01-16 00:15:11 +00001728 char *s;
1729 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001730
Martin v. Löwisffad6332002-11-26 09:28:05 +00001731 if (PyTuple_Size(args) == 1) {
1732 PyObject *o = PyTuple_GetItem(args, 0);
1733 if (PyInt_Check(o)) {
1734 Py_INCREF(o);
1735 return o;
1736 }
1737 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001738 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001739 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001740 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1741 return Tkinter_Error(self);
Barry Warsawfa701a81997-01-16 00:15:11 +00001742 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001743}
1744
1745static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001746Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001747{
Barry Warsawfa701a81997-01-16 00:15:11 +00001748 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001749 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001750 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001751
Guido van Rossum43713e52000-02-29 13:59:29 +00001752 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001753 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001754
1755 CHECK_TCL_APPARTMENT;
1756
Guido van Rossum00d93061998-05-28 23:06:38 +00001757 ENTER_TCL
1758 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001759 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001760 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001761 res = Tkinter_Error(self);
1762 else
1763 res = Py_BuildValue("s", Tkapp_Result(self));
1764 LEAVE_OVERLAP_TCL
1765 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001766}
1767
1768static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001769Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001770{
Barry Warsawfa701a81997-01-16 00:15:11 +00001771 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001772 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001773 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001774 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001775
Guido van Rossum43713e52000-02-29 13:59:29 +00001776 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001777 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001778
1779 CHECK_TCL_APPARTMENT;
1780
Guido van Rossum00d93061998-05-28 23:06:38 +00001781 ENTER_TCL
1782 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001783 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001784 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001785 res = Tkinter_Error(self);
1786 else
1787 res = Py_BuildValue("l", v);
1788 LEAVE_OVERLAP_TCL
1789 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001790}
1791
1792static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001793Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001794{
Barry Warsawfa701a81997-01-16 00:15:11 +00001795 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001796 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001797 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001798 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001799
Guido van Rossum43713e52000-02-29 13:59:29 +00001800 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001801 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001802 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001803 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001804 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001805 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001806 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001807 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001808 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001809 res = Tkinter_Error(self);
1810 else
1811 res = Py_BuildValue("d", v);
1812 LEAVE_OVERLAP_TCL
1813 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001814}
1815
1816static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001817Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001818{
Barry Warsawfa701a81997-01-16 00:15:11 +00001819 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001820 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001821 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001822 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001823
Guido van Rossum43713e52000-02-29 13:59:29 +00001824 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001825 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001826 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001827 ENTER_TCL
1828 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001829 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001830 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001831 res = Tkinter_Error(self);
1832 else
1833 res = Py_BuildValue("i", v);
1834 LEAVE_OVERLAP_TCL
1835 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001836}
1837
Barry Warsawfa701a81997-01-16 00:15:11 +00001838
1839
Guido van Rossum18468821994-06-20 07:49:28 +00001840static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001841Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001842{
Barry Warsawfa701a81997-01-16 00:15:11 +00001843 char *list;
1844 int argc;
1845 char **argv;
1846 PyObject *v;
1847 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001848
Martin v. Löwisffad6332002-11-26 09:28:05 +00001849 if (PyTuple_Size(args) == 1) {
1850 v = PyTuple_GetItem(args, 0);
1851 if (PyTuple_Check(v)) {
1852 Py_INCREF(v);
1853 return v;
1854 }
1855 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001856 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001857 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001858
Barry Warsawfa701a81997-01-16 00:15:11 +00001859 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1860 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001861
Barry Warsawfa701a81997-01-16 00:15:11 +00001862 if (!(v = PyTuple_New(argc)))
1863 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001864
Barry Warsawfa701a81997-01-16 00:15:11 +00001865 for (i = 0; i < argc; i++) {
1866 PyObject *s = PyString_FromString(argv[i]);
1867 if (!s || PyTuple_SetItem(v, i, s)) {
1868 Py_DECREF(v);
1869 v = NULL;
1870 goto finally;
1871 }
1872 }
Guido van Rossum18468821994-06-20 07:49:28 +00001873
Barry Warsawfa701a81997-01-16 00:15:11 +00001874 finally:
1875 ckfree(FREECAST argv);
1876 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001877}
1878
1879static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001880Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001881{
Barry Warsawfa701a81997-01-16 00:15:11 +00001882 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001883
Martin v. Löwisffad6332002-11-26 09:28:05 +00001884 if (PyTuple_Size(args) == 1) {
1885 PyObject* o = PyTuple_GetItem(args, 0);
1886 if (PyTuple_Check(o)) {
1887 o = SplitObj(o);
1888 return o;
1889 }
1890 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001891 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001892 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001893 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001894}
1895
1896static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001897Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001898{
Barry Warsawfa701a81997-01-16 00:15:11 +00001899 char *s = Merge(args);
1900 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001901
Barry Warsawfa701a81997-01-16 00:15:11 +00001902 if (s) {
1903 res = PyString_FromString(s);
1904 ckfree(s);
1905 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001906
1907 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001908}
1909
Barry Warsawfa701a81997-01-16 00:15:11 +00001910
1911
Guido van Rossum18468821994-06-20 07:49:28 +00001912/** Tcl Command **/
1913
Guido van Rossum00d93061998-05-28 23:06:38 +00001914/* Client data struct */
1915typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001916 PyObject *self;
1917 PyObject *func;
1918} PythonCmd_ClientData;
1919
1920static int
Fred Drake509d79a2000-07-08 04:04:38 +00001921PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001922{
1923 errorInCmd = 1;
1924 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1925 LEAVE_PYTHON
1926 return TCL_ERROR;
1927}
1928
Guido van Rossum18468821994-06-20 07:49:28 +00001929/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001930 * function or method.
1931 */
Guido van Rossum18468821994-06-20 07:49:28 +00001932static int
Fred Drake509d79a2000-07-08 04:04:38 +00001933PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001934{
Guido van Rossum00d93061998-05-28 23:06:38 +00001935 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001936 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001937 int i, rv;
1938 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001939
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001940 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001941
Barry Warsawfa701a81997-01-16 00:15:11 +00001942 /* TBD: no error checking here since we know, via the
1943 * Tkapp_CreateCommand() that the client data is a two-tuple
1944 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001945 self = data->self;
1946 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001947
Barry Warsawfa701a81997-01-16 00:15:11 +00001948 /* Create argument list (argv1, ..., argvN) */
1949 if (!(arg = PyTuple_New(argc - 1)))
1950 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001951
Barry Warsawfa701a81997-01-16 00:15:11 +00001952 for (i = 0; i < (argc - 1); i++) {
1953 PyObject *s = PyString_FromString(argv[i + 1]);
1954 if (!s || PyTuple_SetItem(arg, i, s)) {
1955 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001956 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001957 }
1958 }
1959 res = PyEval_CallObject(func, arg);
1960 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001961
Barry Warsawfa701a81997-01-16 00:15:11 +00001962 if (res == NULL)
1963 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001964
Barry Warsawfa701a81997-01-16 00:15:11 +00001965 if (!(tmp = PyList_New(0))) {
1966 Py_DECREF(res);
1967 return PythonCmd_Error(interp);
1968 }
1969
Guido van Rossum2834b972000-10-06 16:58:26 +00001970 s = AsString(res, tmp);
1971 if (s == NULL) {
1972 rv = PythonCmd_Error(interp);
1973 }
1974 else {
1975 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1976 rv = TCL_OK;
1977 }
1978
Barry Warsawfa701a81997-01-16 00:15:11 +00001979 Py_DECREF(res);
1980 Py_DECREF(tmp);
1981
Guido van Rossum00d93061998-05-28 23:06:38 +00001982 LEAVE_PYTHON
1983
Guido van Rossum2834b972000-10-06 16:58:26 +00001984 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001985}
1986
1987static void
Fred Drake509d79a2000-07-08 04:04:38 +00001988PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001989{
Guido van Rossum00d93061998-05-28 23:06:38 +00001990 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1991
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001992 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001993 Py_XDECREF(data->self);
1994 Py_XDECREF(data->func);
1995 PyMem_DEL(data);
1996 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001997}
1998
Barry Warsawfa701a81997-01-16 00:15:11 +00001999
2000
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002001
2002TCL_DECLARE_MUTEX(command_mutex)
2003
2004typedef struct CommandEvent{
2005 Tcl_Event ev;
2006 Tcl_Interp* interp;
2007 char *name;
2008 int create;
2009 int *status;
2010 ClientData *data;
2011 Tcl_Condition done;
2012} CommandEvent;
2013
2014static int
2015Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002016{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002017 if (ev->create)
2018 *ev->status = Tcl_CreateCommand(
2019 ev->interp, ev->name, PythonCmd,
2020 ev->data, PythonCmdDelete) == NULL;
2021 else
2022 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2023 Tcl_MutexLock(&command_mutex);
2024 Tcl_ConditionNotify(&ev->done);
2025 Tcl_MutexUnlock(&command_mutex);
2026 return 1;
2027}
2028
2029static PyObject *
2030Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2031{
2032 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002033 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002034 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002035 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002036 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002037
Guido van Rossum43713e52000-02-29 13:59:29 +00002038 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002039 return NULL;
2040 if (!PyCallable_Check(func)) {
2041 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002042 return NULL;
2043 }
Guido van Rossum18468821994-06-20 07:49:28 +00002044
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002045 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002046 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002047 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002048
Guido van Rossum00d93061998-05-28 23:06:38 +00002049 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002050 if (!data)
2051 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002052 Py_XINCREF(self);
2053 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002054 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002055 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002056
2057 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2058 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2059 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2060 ev->interp = self->interp;
2061 ev->create = 1;
2062 ev->name = cmdName;
2063 ev->data = (ClientData)data;
2064 ev->status = &err;
2065 ev->done = NULL;
2066 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2067 }
2068 else {
2069 ENTER_TCL
2070 err = Tcl_CreateCommand(
2071 Tkapp_Interp(self), cmdName, PythonCmd,
2072 (ClientData)data, PythonCmdDelete) == NULL;
2073 LEAVE_TCL
2074 }
2075 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002076 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002077 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002078 return NULL;
2079 }
Guido van Rossum18468821994-06-20 07:49:28 +00002080
Barry Warsawfa701a81997-01-16 00:15:11 +00002081 Py_INCREF(Py_None);
2082 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002083}
2084
Barry Warsawfa701a81997-01-16 00:15:11 +00002085
2086
Guido van Rossum18468821994-06-20 07:49:28 +00002087static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002088Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002089{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002090 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002091 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002092 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002093
Guido van Rossum43713e52000-02-29 13:59:29 +00002094 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002095 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002096 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2097 CommandEvent *ev;
2098 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2099 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2100 ev->interp = self->interp;
2101 ev->create = 0;
2102 ev->name = cmdName;
2103 ev->status = &err;
2104 ev->done = NULL;
2105 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2106 &command_mutex);
2107 }
2108 else {
2109 ENTER_TCL
2110 err = Tcl_DeleteCommand(self->interp, cmdName);
2111 LEAVE_TCL
2112 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002113 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002114 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2115 return NULL;
2116 }
2117 Py_INCREF(Py_None);
2118 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002119}
2120
Barry Warsawfa701a81997-01-16 00:15:11 +00002121
2122
Guido van Rossum00d93061998-05-28 23:06:38 +00002123#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002124/** File Handler **/
2125
Guido van Rossum00d93061998-05-28 23:06:38 +00002126typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002127 PyObject *func;
2128 PyObject *file;
2129 int id;
2130 struct _fhcdata *next;
2131} FileHandler_ClientData;
2132
2133static FileHandler_ClientData *HeadFHCD;
2134
2135static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002136NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002137{
2138 FileHandler_ClientData *p;
2139 p = PyMem_NEW(FileHandler_ClientData, 1);
2140 if (p != NULL) {
2141 Py_XINCREF(func);
2142 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002143 p->func = func;
2144 p->file = file;
2145 p->id = id;
2146 p->next = HeadFHCD;
2147 HeadFHCD = p;
2148 }
2149 return p;
2150}
2151
2152static void
Fred Drake509d79a2000-07-08 04:04:38 +00002153DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002154{
2155 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002156
2157 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002158 while ((p = *pp) != NULL) {
2159 if (p->id == id) {
2160 *pp = p->next;
2161 Py_XDECREF(p->func);
2162 Py_XDECREF(p->file);
2163 PyMem_DEL(p);
2164 }
2165 else
2166 pp = &p->next;
2167 }
2168}
2169
Guido van Rossuma597dde1995-01-10 20:56:29 +00002170static void
Fred Drake509d79a2000-07-08 04:04:38 +00002171FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002172{
Guido van Rossum00d93061998-05-28 23:06:38 +00002173 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002174 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002175
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002176 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002177 func = data->func;
2178 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002179
Barry Warsawfa701a81997-01-16 00:15:11 +00002180 arg = Py_BuildValue("(Oi)", file, (long) mask);
2181 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002182 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002183
2184 if (res == NULL) {
2185 errorInCmd = 1;
2186 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2187 }
2188 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002189 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002190}
2191
Guido van Rossum18468821994-06-20 07:49:28 +00002192static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002193Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2194 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002195{
Guido van Rossum00d93061998-05-28 23:06:38 +00002196 FileHandler_ClientData *data;
2197 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002198 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002199
Guido van Rossum2834b972000-10-06 16:58:26 +00002200 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2201 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002202 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002203 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002204 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002205 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002206 return NULL;
2207 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002208 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002209 return NULL;
2210 }
2211
Guido van Rossuma80649b2000-03-28 20:07:05 +00002212 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002213 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002214 return NULL;
2215
Barry Warsawfa701a81997-01-16 00:15:11 +00002216 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002217 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002218 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002219 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002220 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002221 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002222}
2223
2224static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002225Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002226{
Barry Warsawfa701a81997-01-16 00:15:11 +00002227 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002228 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002229
Guido van Rossum43713e52000-02-29 13:59:29 +00002230 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002231 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002232 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002233 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002234 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002235 return NULL;
2236
Guido van Rossuma80649b2000-03-28 20:07:05 +00002237 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002238
Barry Warsawfa701a81997-01-16 00:15:11 +00002239 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002240 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002241 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002242 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002243 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002244 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002245}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002246#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002247
Barry Warsawfa701a81997-01-16 00:15:11 +00002248
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002249/**** Tktt Object (timer token) ****/
2250
Jeremy Hylton938ace62002-07-17 16:30:39 +00002251static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002252
Guido van Rossum00d93061998-05-28 23:06:38 +00002253typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002254 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002255 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002256 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002257} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002258
2259static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002260Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002261{
Barry Warsawfa701a81997-01-16 00:15:11 +00002262 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002263 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002264
Guido van Rossum43713e52000-02-29 13:59:29 +00002265 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002266 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002267 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002268 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002269 v->token = NULL;
2270 }
2271 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002272 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002273 Py_DECREF(func);
2274 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002275 }
2276 Py_INCREF(Py_None);
2277 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002278}
2279
2280static PyMethodDef Tktt_methods[] =
2281{
Neal Norwitzb0493252002-03-31 14:44:22 +00002282 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002283 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002284};
2285
2286static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002287Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002288{
Barry Warsawfa701a81997-01-16 00:15:11 +00002289 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002290
Guido van Rossumb18618d2000-05-03 23:44:39 +00002291 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002292 if (v == NULL)
2293 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002294
Guido van Rossum00d93061998-05-28 23:06:38 +00002295 Py_INCREF(func);
2296 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002297 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002298
2299 /* Extra reference, deleted when called or when handler is deleted */
2300 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002301 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002302}
2303
2304static void
Fred Drake509d79a2000-07-08 04:04:38 +00002305Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002306{
Guido van Rossum00d93061998-05-28 23:06:38 +00002307 TkttObject *v = (TkttObject *)self;
2308 PyObject *func = v->func;
2309
2310 Py_XDECREF(func);
2311
Guido van Rossumb18618d2000-05-03 23:44:39 +00002312 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002313}
2314
Guido van Rossum597ac201998-05-12 14:36:19 +00002315static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002316Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002317{
Barry Warsawfa701a81997-01-16 00:15:11 +00002318 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002319 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002320
Tim Peters885d4572001-11-28 20:27:42 +00002321 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002322 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002323 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002324}
2325
2326static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002327Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002328{
Barry Warsawfa701a81997-01-16 00:15:11 +00002329 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002330}
2331
2332static PyTypeObject Tktt_Type =
2333{
Guido van Rossum35d43371997-08-02 00:09:09 +00002334 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002335 0, /*ob_size */
2336 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002337 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002338 0, /*tp_itemsize */
2339 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002340 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002341 Tktt_GetAttr, /*tp_getattr */
2342 0, /*tp_setattr */
2343 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002344 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002345 0, /*tp_as_number */
2346 0, /*tp_as_sequence */
2347 0, /*tp_as_mapping */
2348 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002349};
2350
Barry Warsawfa701a81997-01-16 00:15:11 +00002351
2352
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002353/** Timer Handler **/
2354
2355static void
Fred Drake509d79a2000-07-08 04:04:38 +00002356TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002357{
Guido van Rossum00d93061998-05-28 23:06:38 +00002358 TkttObject *v = (TkttObject *)clientData;
2359 PyObject *func = v->func;
2360 PyObject *res;
2361
2362 if (func == NULL)
2363 return;
2364
2365 v->func = NULL;
2366
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002367 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002368
2369 res = PyEval_CallObject(func, NULL);
2370 Py_DECREF(func);
2371 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002372
Barry Warsawfa701a81997-01-16 00:15:11 +00002373 if (res == NULL) {
2374 errorInCmd = 1;
2375 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2376 }
2377 else
2378 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002379
2380 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002381}
2382
2383static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002384Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002385{
Barry Warsawfa701a81997-01-16 00:15:11 +00002386 int milliseconds;
2387 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002388 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002389
Guido van Rossum2834b972000-10-06 16:58:26 +00002390 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2391 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002392 return NULL;
2393 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002394 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002395 return NULL;
2396 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002397 v = Tktt_New(func);
2398 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2399 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002400
Guido van Rossum00d93061998-05-28 23:06:38 +00002401 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002402}
2403
Barry Warsawfa701a81997-01-16 00:15:11 +00002404
Guido van Rossum18468821994-06-20 07:49:28 +00002405/** Event Loop **/
2406
Guido van Rossum18468821994-06-20 07:49:28 +00002407static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002408Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002409{
Barry Warsawfa701a81997-01-16 00:15:11 +00002410 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002411 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002412#ifdef WITH_THREAD
2413 PyThreadState *tstate = PyThreadState_Get();
2414#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002415
Guido van Rossum43713e52000-02-29 13:59:29 +00002416 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002417 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002418
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002419 CHECK_TCL_APPARTMENT;
2420
Barry Warsawfa701a81997-01-16 00:15:11 +00002421 quitMainLoop = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002422 self->dispatching = 1;
Barry Warsawfa701a81997-01-16 00:15:11 +00002423 while (Tk_GetNumMainWindows() > threshold &&
2424 !quitMainLoop &&
2425 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002426 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002427 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002428
2429#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002430 if (self->threaded) {
2431 /* Allow other Python threads to run. */
2432 ENTER_TCL
2433 result = Tcl_DoOneEvent(0);
2434 LEAVE_TCL
2435 }
2436 else {
2437 Py_BEGIN_ALLOW_THREADS
2438 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2439 tcl_tstate = tstate;
2440 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2441 tcl_tstate = NULL;
2442 if(tcl_lock)PyThread_release_lock(tcl_lock);
2443 if (result == 0)
2444 Sleep(20);
2445 Py_END_ALLOW_THREADS
2446 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002447#else
2448 result = Tcl_DoOneEvent(0);
2449#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002450
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002451 if (PyErr_CheckSignals() != 0) {
2452 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002453 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002454 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002455 if (result < 0)
2456 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002457 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002458 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002459 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002460
Barry Warsawfa701a81997-01-16 00:15:11 +00002461 if (errorInCmd) {
2462 errorInCmd = 0;
2463 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2464 excInCmd = valInCmd = trbInCmd = NULL;
2465 return NULL;
2466 }
2467 Py_INCREF(Py_None);
2468 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002469}
2470
2471static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002472Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002473{
Guido van Rossum35d43371997-08-02 00:09:09 +00002474 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002475 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002476
Guido van Rossum43713e52000-02-29 13:59:29 +00002477 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002478 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002479 CHECK_TCL_APPARTMENT;
Barry Warsawfa701a81997-01-16 00:15:11 +00002480
Guido van Rossum00d93061998-05-28 23:06:38 +00002481 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002482 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002483 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002484 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002485}
2486
2487static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002488Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002489{
2490
Guido van Rossum43713e52000-02-29 13:59:29 +00002491 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002492 return NULL;
2493
2494 quitMainLoop = 1;
2495 Py_INCREF(Py_None);
2496 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002497}
2498
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002499static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002500Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002501{
2502
Guido van Rossum43713e52000-02-29 13:59:29 +00002503 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002504 return NULL;
2505
2506 return PyInt_FromLong((long)Tkapp_Interp(self));
2507}
2508
Barry Warsawfa701a81997-01-16 00:15:11 +00002509
Martin v. Löwisffad6332002-11-26 09:28:05 +00002510static PyObject *
2511Tkapp_WantObjects(PyObject *self, PyObject *args)
2512{
2513
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002514 int wantobjects;
2515 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002516 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002517 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002518
2519 Py_INCREF(Py_None);
2520 return Py_None;
2521}
2522
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002523static PyObject *
2524Tkapp_WillDispatch(PyObject *self, PyObject *args)
2525{
2526
2527 ((TkappObject*)self)->dispatching = 1;
2528
2529 Py_INCREF(Py_None);
2530 return Py_None;
2531}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002532
Barry Warsawfa701a81997-01-16 00:15:11 +00002533
Guido van Rossum18468821994-06-20 07:49:28 +00002534/**** Tkapp Method List ****/
2535
2536static PyMethodDef Tkapp_methods[] =
2537{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002538 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002539 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002540 {"call", Tkapp_Call, METH_OLDARGS},
2541 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2542 {"eval", Tkapp_Eval, METH_VARARGS},
2543 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2544 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2545 {"record", Tkapp_Record, METH_VARARGS},
2546 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2547 {"setvar", Tkapp_SetVar, METH_VARARGS},
2548 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2549 {"getvar", Tkapp_GetVar, METH_VARARGS},
2550 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2551 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2552 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2553 {"getint", Tkapp_GetInt, METH_VARARGS},
2554 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2555 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2556 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2557 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2558 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2559 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2560 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2561 {"split", Tkapp_Split, METH_VARARGS},
2562 {"merge", Tkapp_Merge, METH_OLDARGS},
2563 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2564 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002565#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002566 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2567 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002568#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002569 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2570 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2571 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2572 {"quit", Tkapp_Quit, METH_VARARGS},
2573 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002574 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002575};
2576
Barry Warsawfa701a81997-01-16 00:15:11 +00002577
2578
Guido van Rossum18468821994-06-20 07:49:28 +00002579/**** Tkapp Type Methods ****/
2580
2581static void
Fred Drake509d79a2000-07-08 04:04:38 +00002582Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002583{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002584 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002585 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002586 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002587 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002588 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002589 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002590}
2591
2592static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002593Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002594{
Guido van Rossum35d43371997-08-02 00:09:09 +00002595 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002596}
2597
2598static PyTypeObject Tkapp_Type =
2599{
Guido van Rossum35d43371997-08-02 00:09:09 +00002600 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002601 0, /*ob_size */
2602 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002603 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002604 0, /*tp_itemsize */
2605 Tkapp_Dealloc, /*tp_dealloc */
2606 0, /*tp_print */
2607 Tkapp_GetAttr, /*tp_getattr */
2608 0, /*tp_setattr */
2609 0, /*tp_compare */
2610 0, /*tp_repr */
2611 0, /*tp_as_number */
2612 0, /*tp_as_sequence */
2613 0, /*tp_as_mapping */
2614 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002615};
2616
Barry Warsawfa701a81997-01-16 00:15:11 +00002617
2618
Guido van Rossum18468821994-06-20 07:49:28 +00002619/**** Tkinter Module ****/
2620
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002621typedef struct {
2622 PyObject* tuple;
2623 int size; /* current size */
2624 int maxsize; /* allocated size */
2625} FlattenContext;
2626
2627static int
2628_bump(FlattenContext* context, int size)
2629{
Guido van Rossum2834b972000-10-06 16:58:26 +00002630 /* expand tuple to hold (at least) size new items.
2631 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002632
2633 int maxsize = context->maxsize * 2;
2634
2635 if (maxsize < context->size + size)
2636 maxsize = context->size + size;
2637
2638 context->maxsize = maxsize;
2639
Tim Peters4324aa32001-05-28 22:30:08 +00002640 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002641}
2642
2643static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002644_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002645{
2646 /* add tuple or list to argument tuple (recursively) */
2647
2648 int i, size;
2649
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002650 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002651 PyErr_SetString(PyExc_ValueError,
2652 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002653 return 0;
2654 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002655 size = PyList_GET_SIZE(item);
2656 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002657 if (context->size + size > context->maxsize &&
2658 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002659 return 0;
2660 /* copy items to output tuple */
2661 for (i = 0; i < size; i++) {
2662 PyObject *o = PyList_GET_ITEM(item, i);
2663 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002664 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002665 return 0;
2666 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002667 if (context->size + 1 > context->maxsize &&
2668 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002669 return 0;
2670 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002671 PyTuple_SET_ITEM(context->tuple,
2672 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002673 }
2674 }
2675 } else if (PyTuple_Check(item)) {
2676 /* same, for tuples */
2677 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002678 if (context->size + size > context->maxsize &&
2679 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002680 return 0;
2681 for (i = 0; i < size; i++) {
2682 PyObject *o = PyTuple_GET_ITEM(item, i);
2683 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002684 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002685 return 0;
2686 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002687 if (context->size + 1 > context->maxsize &&
2688 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002689 return 0;
2690 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002691 PyTuple_SET_ITEM(context->tuple,
2692 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002693 }
2694 }
2695 } else {
2696 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2697 return 0;
2698 }
2699 return 1;
2700}
2701
2702static PyObject *
2703Tkinter_Flatten(PyObject* self, PyObject* args)
2704{
2705 FlattenContext context;
2706 PyObject* item;
2707
2708 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2709 return NULL;
2710
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002711 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002712 if (context.maxsize <= 0)
2713 return PyTuple_New(0);
2714
2715 context.tuple = PyTuple_New(context.maxsize);
2716 if (!context.tuple)
2717 return NULL;
2718
2719 context.size = 0;
2720
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002721 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002722 return NULL;
2723
Tim Peters4324aa32001-05-28 22:30:08 +00002724 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002725 return NULL;
2726
2727 return context.tuple;
2728}
2729
Guido van Rossum18468821994-06-20 07:49:28 +00002730static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002731Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002732{
Barry Warsawfa701a81997-01-16 00:15:11 +00002733 char *screenName = NULL;
2734 char *baseName = NULL;
2735 char *className = NULL;
2736 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002737 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002738
Guido van Rossum35d43371997-08-02 00:09:09 +00002739 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002740 if (baseName != NULL)
2741 baseName++;
2742 else
2743 baseName = Py_GetProgramName();
2744 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002745
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002746 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002747 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002748 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002749 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002750
Barry Warsawfa701a81997-01-16 00:15:11 +00002751 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002752 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002753}
2754
2755static PyMethodDef moduleMethods[] =
2756{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002757 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2758 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002759#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002760 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2761 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002762#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002763 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2764 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2765 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2766 {"quit", Tkapp_Quit, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002767 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002768};
2769
Guido van Rossum7bf15641998-05-22 18:28:17 +00002770#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002771
2772static int stdin_ready = 0;
2773
Guido van Rossumad4db171998-06-13 13:56:28 +00002774#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002775static void
Fred Drake509d79a2000-07-08 04:04:38 +00002776MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002777{
2778 stdin_ready = 1;
2779}
Guido van Rossumad4db171998-06-13 13:56:28 +00002780#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002781
Guido van Rossum00d93061998-05-28 23:06:38 +00002782static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002783
Guido van Rossum18468821994-06-20 07:49:28 +00002784static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002785EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002786{
Guido van Rossumad4db171998-06-13 13:56:28 +00002787#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002788 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002789#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002790#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002791 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002792#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002793 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002794 errorInCmd = 0;
2795#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002796 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002797 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002798#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002799 while (!errorInCmd && !stdin_ready) {
2800 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002801#ifdef MS_WINDOWS
2802 if (_kbhit()) {
2803 stdin_ready = 1;
2804 break;
2805 }
2806#endif
2807#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002808 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002809 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002810 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002811
Guido van Rossum00d93061998-05-28 23:06:38 +00002812 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002813
2814 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002815 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002816 if (result == 0)
2817 Sleep(20);
2818 Py_END_ALLOW_THREADS
2819#else
2820 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002821#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002822
2823 if (result < 0)
2824 break;
2825 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002826#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002827 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002828#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002829 if (errorInCmd) {
2830 errorInCmd = 0;
2831 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2832 excInCmd = valInCmd = trbInCmd = NULL;
2833 PyErr_Print();
2834 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002835#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002836 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002837#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002838 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002839}
Guido van Rossum18468821994-06-20 07:49:28 +00002840
Guido van Rossum00d93061998-05-28 23:06:38 +00002841#endif
2842
Guido van Rossum7bf15641998-05-22 18:28:17 +00002843static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002844EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002845{
Guido van Rossum00d93061998-05-28 23:06:38 +00002846#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002847 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002848#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002849 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002850#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002851 PyOS_InputHook = EventHook;
2852 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002853#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002854}
2855
2856static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002857DisableEventHook(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 (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2861 PyOS_InputHook = NULL;
2862 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002863#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002864}
2865
Barry Warsawfa701a81997-01-16 00:15:11 +00002866
2867/* all errors will be checked in one fell swoop in init_tkinter() */
2868static void
Fred Drake509d79a2000-07-08 04:04:38 +00002869ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002870{
2871 PyObject *v = PyInt_FromLong(val);
2872 if (v) {
2873 PyDict_SetItemString(d, name, v);
2874 Py_DECREF(v);
2875 }
2876}
2877static void
Fred Drake509d79a2000-07-08 04:04:38 +00002878ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002879{
2880 PyObject *v = PyString_FromString(val);
2881 if (v) {
2882 PyDict_SetItemString(d, name, v);
2883 Py_DECREF(v);
2884 }
2885}
2886
2887
Mark Hammond62b1ab12002-07-23 06:31:15 +00002888PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002889init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002890{
Barry Warsawfa701a81997-01-16 00:15:11 +00002891 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002892
Barry Warsawfa701a81997-01-16 00:15:11 +00002893 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002894
2895#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002896 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002897#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002898
Barry Warsawfa701a81997-01-16 00:15:11 +00002899 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002900
Barry Warsawfa701a81997-01-16 00:15:11 +00002901 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00002902 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00002903 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002904
Guido van Rossum35d43371997-08-02 00:09:09 +00002905 ins_long(d, "READABLE", TCL_READABLE);
2906 ins_long(d, "WRITABLE", TCL_WRITABLE);
2907 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2908 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2909 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2910 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2911 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2912 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2913 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002914 ins_string(d, "TK_VERSION", TK_VERSION);
2915 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002916
Guido van Rossum83551bf1997-09-13 00:44:23 +00002917 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002918
2919 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002920 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2921
Martin v. Löwisffad6332002-11-26 09:28:05 +00002922 PyTclObject_Type.ob_type = &PyType_Type;
Jason Tishlerbbe89612002-12-31 20:30:46 +00002923 PyTclObject_Type.tp_getattro = &PyObject_GenericGetAttr;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002924 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002925
2926#ifdef TK_AQUA
2927 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2928 * start waking up. Note that Tcl_FindExecutable will do this, this
2929 * code must be above it! The original warning from
2930 * tkMacOSXAppInit.c is copied below.
2931 *
2932 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2933 * Tcl interpreter for now. It probably should work to do this
2934 * in the other order, but for now it doesn't seem to.
2935 *
2936 */
2937 Tk_MacOSXSetupTkNotifier();
2938#endif
2939
2940
Guido van Rossume187b0e2000-03-27 21:46:29 +00002941 /* This helps the dynamic loader; in Unicode aware Tcl versions
2942 it also helps Tcl find its encodings. */
2943 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00002944
Barry Warsawfa701a81997-01-16 00:15:11 +00002945 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002946 return;
2947
Guido van Rossum43ff8681998-07-14 18:02:13 +00002948#if 0
2949 /* This was not a good idea; through <Destroy> bindings,
2950 Tcl_Finalize() may invoke Python code but at that point the
2951 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002952 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002953#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002954
Jack Jansen34cc5c31995-10-31 16:15:12 +00002955#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002956 /*
2957 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2958 ** Most of the initializations in that routine (toolbox init calls and
2959 ** such) have already been done for us, so we only need these.
2960 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002961 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002962
2963 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00002964#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00002965 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00002966#endif /* GENERATINGCFM */
2967#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00002968}
Guido van Rossum9722ad81995-09-22 23:49:28 +00002969
Guido van Rossumec22c921996-02-25 04:50:29 +00002970
Barry Warsawfa701a81997-01-16 00:15:11 +00002971
Guido van Rossum9722ad81995-09-22 23:49:28 +00002972#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002973
2974/*
Guido van Rossumec22c921996-02-25 04:50:29 +00002975** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002976*/
2977
Guido van Rossum9722ad81995-09-22 23:49:28 +00002978void
2979panic(char * format, ...)
2980{
Barry Warsawfa701a81997-01-16 00:15:11 +00002981 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002982
Barry Warsawfa701a81997-01-16 00:15:11 +00002983 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002984
Guido van Rossum227cf761998-08-05 13:53:32 +00002985 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002986 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002987
Barry Warsawfa701a81997-01-16 00:15:11 +00002988 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002989
Barry Warsawfa701a81997-01-16 00:15:11 +00002990 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00002991}
Jack Jansen40b546d1995-11-14 10:34:45 +00002992
Guido van Rossumec22c921996-02-25 04:50:29 +00002993/*
2994** Pass events to SIOUX before passing them to Tk.
2995*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002996
Guido van Rossumec22c921996-02-25 04:50:29 +00002997static int
Fred Drake509d79a2000-07-08 04:04:38 +00002998PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002999{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003000 WindowPtr frontwin;
3001 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00003002 ** Sioux eats too many events, so we don't pass it everything. We
3003 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003004 ** the Sioux window is frontmost. This means that Tk menus don't work
3005 ** in that case, but at least we can scroll the sioux window.
3006 ** Note that the SIOUXIsAppWindow() routine we use here is not really
3007 ** part of the external interface of Sioux...
3008 */
3009 frontwin = FrontWindow();
3010 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
3011 if (SIOUXHandleOneEvent(eventPtr))
3012 return 0; /* Nothing happened to the Tcl event queue */
3013 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003014 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003015}
3016
Guido van Rossumec22c921996-02-25 04:50:29 +00003017#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003018
3019/*
3020** Additional Mac specific code for dealing with shared libraries.
3021*/
3022
3023#include <Resources.h>
3024#include <CodeFragments.h>
3025
3026static int loaded_from_shlib = 0;
3027static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003028
Jack Jansen34cc5c31995-10-31 16:15:12 +00003029/*
3030** If this module is dynamically loaded the following routine should
3031** be the init routine. It takes care of adding the shared library to
3032** the resource-file chain, so that the tk routines can find their
3033** resources.
3034*/
3035OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003036init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003037{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00003038 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00003039 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003040 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003041 library_fss = *data->fragLocator.u.onDisk.fileSpec;
3042 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003043 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003044 library_fss = *data->fragLocator.u.inSegs.fileSpec;
3045 loaded_from_shlib = 1;
3046 }
3047 return noErr;
3048}
3049
3050/*
3051** Insert the library resources into the search path. Put them after
3052** the resources from the application. Again, we ignore errors.
3053*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003054static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003055mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003056{
3057 if ( !loaded_from_shlib )
3058 return;
3059 (void)FSpOpenResFile(&library_fss, fsRdPerm);
3060}
3061
Guido van Rossumec22c921996-02-25 04:50:29 +00003062#endif /* GENERATINGCFM */
3063#endif /* macintosh */