blob: 212bbadf19be926d9bfeb1448b1f61a7f4005b42 [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öwis71e25a02002-10-01 18:08:06 +000040/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
41 making _tkinter correct for this API means to break earlier
42 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
43 earlier versions. Once Tcl releases before 8.4 don't need to be supported
44 anymore, this should go. */
45#define USE_COMPAT_CONST
46
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000047/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
48 it always; if Tcl is not threaded, the thread functions in
49 Tcl are empty. */
50#define TCL_THREADS
51
Jack Jansencb852442001-12-09 23:15:56 +000052#ifdef TK_FRAMEWORK
53#include <Tcl/tcl.h>
54#include <Tk/tk.h>
55#else
Guido van Rossum18468821994-06-20 07:49:28 +000056#include <tcl.h>
57#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000058#endif
Guido van Rossum18468821994-06-20 07:49:28 +000059
Jason Tishlerbbe89612002-12-31 20:30:46 +000060/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000061#ifndef CONST84_RETURN
62#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000063#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000064#define CONST
65#endif
66
Guido van Rossum3e819a71997-08-01 19:29:02 +000067#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
68
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000069#if TKMAJORMINOR < 8002
70#error "Tk older than 8.2 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000071#endif
72
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000073/* Unicode conversion assumes that Tcl_UniChar is two bytes.
74 We cannot test this directly, so we test UTF-8 size instead,
75 expecting that TCL_UTF_MAX is changed if Tcl ever supports
76 either UTF-16 or UCS-4. */
77#if TCL_UTF_MAX != 3
78#error "unsupported Tcl configuration"
79#endif
80
Guido van Rossuma80649b2000-03-28 20:07:05 +000081#if defined(macintosh)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000082/* Sigh, we have to include this to get at the tcl qd pointer */
83#include <tkMac.h>
Guido van Rossum2ea1c941998-04-28 16:12:43 +000084/* And this one we need to clear the menu bar */
85#include <Menus.h>
Guido van Rossum0d2390c1997-08-14 19:57:07 +000086#endif
87
Jack Jansen84c10b12001-07-16 19:32:52 +000088#if !(defined(MS_WINDOWS) || defined(__CYGWIN__) || defined(macintosh))
89/* Mac has it, but it doesn't really work:-( */
Guido van Rossum0d2390c1997-08-14 19:57:07 +000090#define HAVE_CREATEFILEHANDLER
91#endif
92
Guido van Rossum00d93061998-05-28 23:06:38 +000093#ifdef HAVE_CREATEFILEHANDLER
94
95/* Tcl_CreateFileHandler() changed several times; these macros deal with the
96 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
97 Unix, only because Jack added it back); when available on Windows, it only
98 applies to sockets. */
99
Guido van Rossum7bf15641998-05-22 18:28:17 +0000100#ifdef MS_WINDOWS
101#define FHANDLETYPE TCL_WIN_SOCKET
102#else
103#define FHANDLETYPE TCL_UNIX_FD
104#endif
105
Guido van Rossum00d93061998-05-28 23:06:38 +0000106/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
107 which uses this to handle Tcl events while the user is typing commands. */
108
109#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000110#define WAIT_FOR_STDIN
111#endif
112
Guido van Rossum00d93061998-05-28 23:06:38 +0000113#endif /* HAVE_CREATEFILEHANDLER */
114
Guido van Rossumad4db171998-06-13 13:56:28 +0000115#ifdef MS_WINDOWS
116#include <conio.h>
117#define WAIT_FOR_STDIN
118#endif
119
Guido van Rossum00d93061998-05-28 23:06:38 +0000120#ifdef WITH_THREAD
121
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000122/* The threading situation is complicated. Tcl is not thread-safe, except
123 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000124 So we need to use a lock around all uses of Tcl. Previously, the Python
125 interpreter lock was used for this. However, this causes problems when
126 other Python threads need to run while Tcl is blocked waiting for events.
127
128 To solve this problem, a separate lock for Tcl is introduced. Holding it
129 is incompatible with holding Python's interpreter lock. The following four
130 macros manipulate both locks together.
131
132 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
133 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
134 that could call an event handler, or otherwise affect the state of a Tcl
135 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000136 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000137 released and the lock for Tcl has been acquired.
138
Guido van Rossum5e977831998-06-15 14:03:52 +0000139 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
140 (For example, when transferring data from the Tcl interpreter result to a
141 Python string object.) This can be done by using different macros to close
142 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
143 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
144 releases the Tcl lock.
145
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000146 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000147 handlers when the handler needs to use Python. Such event handlers are
148 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000149 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000150 the Python interpreter lock, restoring the appropriate thread state, and
151 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
152 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000153 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000154
155 These locks expand to several statements and brackets; they should not be
156 used in branches of if statements and the like.
157
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000158 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
159 only valid in the thread that created it, and all Tk activity must happen in this
160 thread, also. That means that the mainloop must be invoked in the thread that
161 created the interpreter. Invoking commands from other threads is possible;
162 _tkinter will queue an event for the interpreter thread, which will then
163 execute the command and pass back the result. If the main thread is not in the
164 mainloop, and invoking commands causes an exception; if the main loop is running
165 but not processing events, the command invocation will block.
166
167 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
168 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
169 threads. So we use the Tcl TLS API.
170
Guido van Rossum00d93061998-05-28 23:06:38 +0000171*/
172
Guido van Rossum65d5b571998-12-21 19:32:43 +0000173static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000174
175#ifdef TCL_THREADS
176static Tcl_ThreadDataKey state_key;
177typedef PyThreadState *ThreadSpecificData;
178#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
179#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000180static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000181#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000182
183#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000184 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000185 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000186
187#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000188 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000189
Guido van Rossum62320c91998-06-15 04:36:09 +0000190#define ENTER_OVERLAP \
191 Py_END_ALLOW_THREADS
192
193#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000194 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000195
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000196#define ENTER_PYTHON \
197 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000198 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000199
200#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000201 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000202 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
203
204#define CHECK_TCL_APPARTMENT \
205 if (((TkappObject *)self)->threaded && \
206 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
207 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
208 return 0; \
209 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000210
211#else
212
213#define ENTER_TCL
214#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000215#define ENTER_OVERLAP
216#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000217#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000218#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000219#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000220
221#endif
222
Guido van Rossumec22c921996-02-25 04:50:29 +0000223#ifdef macintosh
224
225/*
226** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000227** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000228*/
229
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000230/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000231#define FREECAST (char *)
232
Guido van Rossumec22c921996-02-25 04:50:29 +0000233#include <Events.h> /* For EventRecord */
234
Fred Drake509d79a2000-07-08 04:04:38 +0000235typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
Guido van Rossum2834b972000-10-06 16:58:26 +0000236void Tcl_MacSetEventProc(TclMacConvertEventPtr procPtr);
237int TkMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000238
Jeremy Hylton938ace62002-07-17 16:30:39 +0000239static int PyMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000240
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000241#include <SIOUX.h>
242extern int SIOUXIsAppWindow(WindowPtr);
243
Guido van Rossumec22c921996-02-25 04:50:29 +0000244#endif /* macintosh */
245
Guido van Rossum97867b21996-08-08 19:09:53 +0000246#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000247#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000248#endif
249
Guido van Rossum18468821994-06-20 07:49:28 +0000250/**** Tkapp Object Declaration ****/
251
Jeremy Hylton938ace62002-07-17 16:30:39 +0000252static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000253
Guido van Rossum00d93061998-05-28 23:06:38 +0000254typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000255 PyObject_HEAD
256 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000257 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000258 int threaded; /* True if tcl_platform[threaded] */
259 Tcl_ThreadId thread_id;
260 int dispatching;
261 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000262 So we cache interesting types here. */
263 Tcl_ObjType *BooleanType;
264 Tcl_ObjType *ByteArrayType;
265 Tcl_ObjType *DoubleType;
266 Tcl_ObjType *IntType;
267 Tcl_ObjType *ListType;
268 Tcl_ObjType *ProcBodyType;
269 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000270} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000271
272#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000273#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000274#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000275
Guido van Rossum35d43371997-08-02 00:09:09 +0000276#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000277(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000278
Barry Warsawfa701a81997-01-16 00:15:11 +0000279
280
Guido van Rossum18468821994-06-20 07:49:28 +0000281/**** Error Handling ****/
282
283static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000284static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000285static int errorInCmd = 0;
286static PyObject *excInCmd;
287static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000288static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000289
Barry Warsawfa701a81997-01-16 00:15:11 +0000290
291
Guido van Rossum18468821994-06-20 07:49:28 +0000292static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000293Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000294{
Barry Warsawfa701a81997-01-16 00:15:11 +0000295 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
296 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000297}
298
Barry Warsawfa701a81997-01-16 00:15:11 +0000299
Barry Warsawfa701a81997-01-16 00:15:11 +0000300
Guido van Rossum18468821994-06-20 07:49:28 +0000301/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000302
303#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000304#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000305
Guido van Rossum00d93061998-05-28 23:06:38 +0000306/* Millisecond sleep() for Unix platforms. */
307
308static void
Fred Drake509d79a2000-07-08 04:04:38 +0000309Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000310{
311 /* XXX Too bad if you don't have select(). */
312 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000313 t.tv_sec = milli/1000;
314 t.tv_usec = (milli%1000) * 1000;
315 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
316}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000317#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000318#endif /* WITH_THREAD */
319
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000320/* Wait up to 1s for the mainloop to come up. */
321
322static int
323WaitForMainloop(TkappObject* self)
324{
325 int i;
326 for (i = 0; i < 10; i++) {
327 if (self->dispatching)
328 return 1;
329 Py_BEGIN_ALLOW_THREADS
330 Sleep(100);
331 Py_END_ALLOW_THREADS
332 }
333 if (self->dispatching)
334 return 1;
335 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
336 return 0;
337}
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000338
Guido van Rossum00d93061998-05-28 23:06:38 +0000339
Guido van Rossum18468821994-06-20 07:49:28 +0000340static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000341AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000342{
Guido van Rossum35d43371997-08-02 00:09:09 +0000343 if (PyString_Check(value))
344 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000345#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000346 else if (PyUnicode_Check(value)) {
347 PyObject *v = PyUnicode_AsUTF8String(value);
348 if (v == NULL)
349 return NULL;
350 if (PyList_Append(tmp, v) != 0) {
351 Py_DECREF(v);
352 return NULL;
353 }
354 Py_DECREF(v);
355 return PyString_AsString(v);
356 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000357#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000358 else {
359 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000360 if (v == NULL)
361 return NULL;
362 if (PyList_Append(tmp, v) != 0) {
363 Py_DECREF(v);
364 return NULL;
365 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000366 Py_DECREF(v);
367 return PyString_AsString(v);
368 }
Guido van Rossum18468821994-06-20 07:49:28 +0000369}
370
Barry Warsawfa701a81997-01-16 00:15:11 +0000371
372
Guido van Rossum18468821994-06-20 07:49:28 +0000373#define ARGSZ 64
374
375static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000376Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000377{
Barry Warsawfa701a81997-01-16 00:15:11 +0000378 PyObject *tmp = NULL;
379 char *argvStore[ARGSZ];
380 char **argv = NULL;
381 int fvStore[ARGSZ];
382 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000383 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000384 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000385
Barry Warsawfa701a81997-01-16 00:15:11 +0000386 if (!(tmp = PyList_New(0)))
387 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000388
Barry Warsawfa701a81997-01-16 00:15:11 +0000389 argv = argvStore;
390 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000391
Barry Warsawfa701a81997-01-16 00:15:11 +0000392 if (args == NULL)
393 argc = 0;
394
395 else if (!PyTuple_Check(args)) {
396 argc = 1;
397 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000398 if (!(argv[0] = AsString(args, tmp)))
399 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000400 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000401 else {
402 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000403
Barry Warsawfa701a81997-01-16 00:15:11 +0000404 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000405 argv = (char **)ckalloc(argc * sizeof(char *));
406 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000407 if (argv == NULL || fv == NULL) {
408 PyErr_NoMemory();
409 goto finally;
410 }
411 }
412
413 for (i = 0; i < argc; i++) {
414 PyObject *v = PyTuple_GetItem(args, i);
415 if (PyTuple_Check(v)) {
416 fv[i] = 1;
417 if (!(argv[i] = Merge(v)))
418 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000419 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000420 }
421 else if (v == Py_None) {
422 argc = i;
423 break;
424 }
425 else {
426 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000427 if (!(argv[i] = AsString(v, tmp)))
428 goto finally;
429 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000430 }
431 }
Guido van Rossum18468821994-06-20 07:49:28 +0000432 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000433 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000434 if (res == NULL)
435 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000436
Barry Warsawfa701a81997-01-16 00:15:11 +0000437 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000438 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000439 if (fv[i]) {
440 ckfree(argv[i]);
441 }
442 if (argv != argvStore)
443 ckfree(FREECAST argv);
444 if (fv != fvStore)
445 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000446
Barry Warsawfa701a81997-01-16 00:15:11 +0000447 Py_DECREF(tmp);
448 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000449}
450
Barry Warsawfa701a81997-01-16 00:15:11 +0000451
452
Guido van Rossum18468821994-06-20 07:49:28 +0000453static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000454Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000455{
Barry Warsawfa701a81997-01-16 00:15:11 +0000456 int argc;
457 char **argv;
458 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000459
Barry Warsawfa701a81997-01-16 00:15:11 +0000460 if (list == NULL) {
461 Py_INCREF(Py_None);
462 return Py_None;
463 }
Guido van Rossum18468821994-06-20 07:49:28 +0000464
Guido van Rossum00d93061998-05-28 23:06:38 +0000465 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000466 /* Not a list.
467 * Could be a quoted string containing funnies, e.g. {"}.
468 * Return the string itself.
469 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000470 return PyString_FromString(list);
471 }
Guido van Rossum18468821994-06-20 07:49:28 +0000472
Barry Warsawfa701a81997-01-16 00:15:11 +0000473 if (argc == 0)
474 v = PyString_FromString("");
475 else if (argc == 1)
476 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000477 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000478 int i;
479 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000480
Barry Warsawfa701a81997-01-16 00:15:11 +0000481 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000482 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000483 Py_DECREF(v);
484 v = NULL;
485 break;
486 }
487 PyTuple_SetItem(v, i, w);
488 }
489 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000490 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000491 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000492}
493
Martin v. Löwisffad6332002-11-26 09:28:05 +0000494/* In some cases, Tcl will still return strings that are supposed to be
495 lists. SplitObj walks through a nested tuple, finding string objects that
496 need to be split. */
497
498PyObject *
499SplitObj(PyObject *arg)
500{
501 if (PyTuple_Check(arg)) {
502 int i, size;
503 PyObject *elem, *newelem, *result;
504
505 size = PyTuple_Size(arg);
506 result = NULL;
507 /* Recursively invoke SplitObj for all tuple items.
508 If this does not return a new object, no action is
509 needed. */
510 for(i = 0; i < size; i++) {
511 elem = PyTuple_GetItem(arg, i);
512 newelem = SplitObj(elem);
513 if (!newelem) {
514 Py_XDECREF(result);
515 return NULL;
516 }
517 if (!result) {
518 int k;
519 if (newelem == elem) {
520 Py_DECREF(newelem);
521 continue;
522 }
523 result = PyTuple_New(size);
524 if (!result)
525 return NULL;
526 for(k = 0; k < i; k++) {
527 elem = PyTuple_GetItem(arg, k);
528 Py_INCREF(elem);
529 PyTuple_SetItem(result, k, elem);
530 }
531 }
532 PyTuple_SetItem(result, i, newelem);
533 }
534 if (result)
535 return result;
536 /* Fall through, returning arg. */
537 }
538 else if (PyString_Check(arg)) {
539 int argc;
540 char **argv;
541 char *list = PyString_AsString(arg);
542
543 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
544 Py_INCREF(arg);
545 return arg;
546 }
547 Tcl_Free(FREECAST argv);
548 if (argc > 1)
549 return Split(PyString_AsString(arg));
550 /* Fall through, returning arg. */
551 }
552 Py_INCREF(arg);
553 return arg;
554}
Barry Warsawfa701a81997-01-16 00:15:11 +0000555
556
Guido van Rossum18468821994-06-20 07:49:28 +0000557/**** Tkapp Object ****/
558
559#ifndef WITH_APPINIT
560int
Fred Drake509d79a2000-07-08 04:04:38 +0000561Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000562{
Barry Warsawfa701a81997-01-16 00:15:11 +0000563 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000564
Barry Warsawfa701a81997-01-16 00:15:11 +0000565 main = Tk_MainWindow(interp);
566 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000567 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000568 return TCL_ERROR;
569 }
570 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000571 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000572 return TCL_ERROR;
573 }
574 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000575}
576#endif /* !WITH_APPINIT */
577
Guido van Rossum18468821994-06-20 07:49:28 +0000578
Barry Warsawfa701a81997-01-16 00:15:11 +0000579
580
581/* Initialize the Tk application; see the `main' function in
582 * `tkMain.c'.
583 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000584
Thomas Wouters58d05102000-07-24 14:43:35 +0000585static void EnableEventHook(void); /* Forward */
586static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000587
Barry Warsawfa701a81997-01-16 00:15:11 +0000588static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000589Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000590 int interactive, int wantobjects)
Barry Warsawfa701a81997-01-16 00:15:11 +0000591{
592 TkappObject *v;
593 char *argv0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000594
Guido van Rossumb18618d2000-05-03 23:44:39 +0000595 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000596 if (v == NULL)
597 return NULL;
598
599 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000600 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000601 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
602 TCL_GLOBAL_ONLY) != NULL;
603 v->thread_id = Tcl_GetCurrentThread();
604 v->dispatching = 0;
605
606#ifndef TCL_THREADS
607 if (v->threaded) {
608 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
609 Py_DECREF(v);
610 return 0;
611 }
612#endif
613 if (v->threaded && tcl_lock) {
614 /* If Tcl is threaded, we don't need the lock. */
615 PyThread_free_lock(tcl_lock);
616 tcl_lock = NULL;
617 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000618
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000619 v->BooleanType = Tcl_GetObjType("boolean");
620 v->ByteArrayType = Tcl_GetObjType("bytearray");
621 v->DoubleType = Tcl_GetObjType("double");
622 v->IntType = Tcl_GetObjType("int");
623 v->ListType = Tcl_GetObjType("list");
624 v->ProcBodyType = Tcl_GetObjType("procbody");
625 v->StringType = Tcl_GetObjType("string");
626
Guido van Rossuma80649b2000-03-28 20:07:05 +0000627#if defined(macintosh)
628 /* This seems to be needed */
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000629 ClearMenuBar();
630 TkMacInitMenus(v->interp);
631#endif
Jack Jansencb852442001-12-09 23:15:56 +0000632
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000633 /* Delete the 'exit' command, which can screw things up */
634 Tcl_DeleteCommand(v->interp, "exit");
635
Barry Warsawfa701a81997-01-16 00:15:11 +0000636 if (screenName != NULL)
637 Tcl_SetVar2(v->interp, "env", "DISPLAY",
638 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000639
Barry Warsawfa701a81997-01-16 00:15:11 +0000640 if (interactive)
641 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
642 else
643 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000644
Barry Warsawfa701a81997-01-16 00:15:11 +0000645 /* This is used to get the application class for Tk 4.1 and up */
646 argv0 = (char*)ckalloc(strlen(className) + 1);
647 if (!argv0) {
648 PyErr_NoMemory();
649 Py_DECREF(v);
650 return NULL;
651 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000652
Barry Warsawfa701a81997-01-16 00:15:11 +0000653 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000654 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000655 argv0[0] = tolower(argv0[0]);
656 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
657 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000658
Barry Warsawfa701a81997-01-16 00:15:11 +0000659 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000660 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000661
Guido van Rossum7bf15641998-05-22 18:28:17 +0000662 EnableEventHook();
663
Barry Warsawfa701a81997-01-16 00:15:11 +0000664 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000665}
666
Barry Warsawfa701a81997-01-16 00:15:11 +0000667
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000668static void
669Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
670 Tcl_Condition *cond, Tcl_Mutex *mutex)
671{
672 Py_BEGIN_ALLOW_THREADS;
673 Tcl_MutexLock(mutex);
674 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
675 Tcl_ThreadAlert(self->thread_id);
676 Tcl_ConditionWait(cond, mutex, NULL);
677 Tcl_MutexUnlock(mutex);
678 Py_END_ALLOW_THREADS
679}
680
Barry Warsawfa701a81997-01-16 00:15:11 +0000681
Guido van Rossum18468821994-06-20 07:49:28 +0000682/** Tcl Eval **/
683
Martin v. Löwisffad6332002-11-26 09:28:05 +0000684typedef struct {
685 PyObject_HEAD
686 Tcl_Obj *value;
687} PyTclObject;
688
689staticforward PyTypeObject PyTclObject_Type;
690#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
691
692static PyObject *
693newPyTclObject(Tcl_Obj *arg)
694{
695 PyTclObject *self;
696 self = PyObject_New(PyTclObject, &PyTclObject_Type);
697 if (self == NULL)
698 return NULL;
699 Tcl_IncrRefCount(arg);
700 self->value = arg;
701 return (PyObject*)self;
702}
703
704static void
705PyTclObject_dealloc(PyTclObject *self)
706{
707 Tcl_DecrRefCount(self->value);
708 PyObject_Del(self);
709}
710
711static PyObject *
712PyTclObject_str(PyTclObject *self)
713{
714 return PyString_FromString(Tcl_GetString(self->value));
715}
716
717static PyObject *
718PyTclObject_repr(PyTclObject *self)
719{
720 char buf[50];
721 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
722 self->value->typePtr->name, (int)self->value);
723 return PyString_FromString(buf);
724}
725
726static PyObject*
727get_typename(PyTclObject* obj, void* ignored)
728{
729 return PyString_FromString(obj->value->typePtr->name);
730}
731
732static PyGetSetDef PyTclObject_getsetlist[] = {
733 {"typename", (getter)get_typename, NULL, "name of the Tcl type"},
734 {0},
735};
736
737statichere PyTypeObject PyTclObject_Type = {
738 PyObject_HEAD_INIT(NULL)
739 0, /*ob_size*/
740 "_tkinter.Tcl_Obj", /*tp_name*/
741 sizeof(PyTclObject), /*tp_basicsize*/
742 0, /*tp_itemsize*/
743 /* methods */
744 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
745 0, /*tp_print*/
746 0, /*tp_getattr*/
747 0, /*tp_setattr*/
748 0, /*tp_compare*/
749 (reprfunc)PyTclObject_repr, /*tp_repr*/
750 0, /*tp_as_number*/
751 0, /*tp_as_sequence*/
752 0, /*tp_as_mapping*/
753 0, /*tp_hash*/
754 0, /*tp_call*/
755 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerbbe89612002-12-31 20:30:46 +0000756 0, /*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000757 0, /*tp_setattro*/
758 0, /*tp_as_buffer*/
759 Py_TPFLAGS_DEFAULT, /*tp_flags*/
760 0, /*tp_doc*/
761 0, /*tp_traverse*/
762 0, /*tp_clear*/
763 0, /*tp_richcompare*/
764 0, /*tp_weaklistoffset*/
765 0, /*tp_iter*/
766 0, /*tp_iternext*/
767 0, /*tp_methods*/
768 0, /*tp_members*/
769 PyTclObject_getsetlist, /*tp_getset*/
770 0, /*tp_base*/
771 0, /*tp_dict*/
772 0, /*tp_descr_get*/
773 0, /*tp_descr_set*/
774 0, /*tp_dictoffset*/
775 0, /*tp_init*/
776 0, /*tp_alloc*/
777 0, /*tp_new*/
778 0, /*tp_free*/
779 0, /*tp_is_gc*/
780};
781
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000782static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000783AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000784{
785 Tcl_Obj *result;
786
787 if (PyString_Check(value))
788 return Tcl_NewStringObj(PyString_AS_STRING(value),
789 PyString_GET_SIZE(value));
790 else if (PyInt_Check(value))
791 return Tcl_NewLongObj(PyInt_AS_LONG(value));
792 else if (PyFloat_Check(value))
793 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
794 else if (PyTuple_Check(value)) {
795 Tcl_Obj **argv = (Tcl_Obj**)
796 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
797 int i;
798 if(!argv)
799 return 0;
800 for(i=0;i<PyTuple_Size(value);i++)
801 argv[i] = AsObj(PyTuple_GetItem(value,i));
802 result = Tcl_NewListObj(PyTuple_Size(value), argv);
803 ckfree(FREECAST argv);
804 return result;
805 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000806#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000807 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000808 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
809 int size = PyUnicode_GET_SIZE(value);
810 /* This #ifdef assumes that Tcl uses UCS-2.
811 See TCL_UTF_MAX test above. */
812#ifdef Py_UNICODE_WIDE
813 Tcl_UniChar *outbuf;
814 int i;
815 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
816 if (!outbuf) {
817 PyErr_NoMemory();
818 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000819 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000820 for (i = 0; i < size; i++) {
821 if (inbuf[i] >= 0x10000) {
822 /* Tcl doesn't do UTF-16, yet. */
823 PyErr_SetString(PyExc_ValueError,
824 "unsupported character");
825 ckfree(FREECAST outbuf);
826 return NULL;
827 }
828 outbuf[i] = inbuf[i];
829 }
830 result = Tcl_NewUnicodeObj(outbuf, size);
831 ckfree(FREECAST outbuf);
832 return result;
833#else
834 return Tcl_NewUnicodeObj(inbuf, size);
835#endif
836
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000837 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000838#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000839 else if(PyTclObject_Check(value)) {
840 Tcl_Obj *v = ((PyTclObject*)value)->value;
841 Tcl_IncrRefCount(v);
842 return v;
843 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000844 else {
845 PyObject *v = PyObject_Str(value);
846 if (!v)
847 return 0;
848 result = AsObj(v);
849 Py_DECREF(v);
850 return result;
851 }
852}
853
Martin v. Löwisffad6332002-11-26 09:28:05 +0000854static PyObject*
855FromObj(PyObject* tkapp, Tcl_Obj *value)
856{
857 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000858 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000859
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000860 if (value->typePtr == NULL) {
861 /* If the result contains any bytes with the top bit set,
862 it's UTF-8 and we should decode it to Unicode */
863#ifdef Py_USING_UNICODE
864 int i;
865 char *s = value->bytes;
866 int len = value->length;
867 for (i = 0; i < len; i++) {
868 if (value->bytes[i] & 0x80)
869 break;
870 }
871
872 if (i == value->length)
873 result = PyString_FromStringAndSize(s, len);
874 else {
875 /* Convert UTF-8 to Unicode string */
876 result = PyUnicode_DecodeUTF8(s, len, "strict");
877 if (result == NULL) {
878 PyErr_Clear();
879 result = PyString_FromStringAndSize(s, len);
880 }
881 }
882#else
883 res = PyString_FromStringAndSize(value->bytes, value->length);
884#endif
885 return result;
886 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000887
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000888 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000889 result = value->internalRep.longValue ? Py_True : Py_False;
890 Py_INCREF(result);
891 return result;
892 }
893
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000894 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000895 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000896 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000897 return PyString_FromStringAndSize(data, size);
898 }
899
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000900 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000901 return PyFloat_FromDouble(value->internalRep.doubleValue);
902 }
903
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000904 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000905 return PyInt_FromLong(value->internalRep.longValue);
906 }
907
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000908 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000909 int size;
910 int i, status;
911 PyObject *elem;
912 Tcl_Obj *tcl_elem;
913
914 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
915 if (status == TCL_ERROR)
916 return Tkinter_Error(tkapp);
917 result = PyTuple_New(size);
918 if (!result)
919 return NULL;
920 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000921 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +0000922 value, i, &tcl_elem);
923 if (status == TCL_ERROR) {
924 Py_DECREF(result);
925 return Tkinter_Error(tkapp);
926 }
927 elem = FromObj(tkapp, tcl_elem);
928 if (!elem) {
929 Py_DECREF(result);
930 return NULL;
931 }
932 PyTuple_SetItem(result, i, elem);
933 }
934 return result;
935 }
936
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000937 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000938 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000939 }
940
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000941 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000942#ifdef Py_USING_UNICODE
943#ifdef Py_UNICODE_WIDE
944 PyObject *result;
945 int size;
946 Tcl_UniChar *input;
947 Py_UNICODE *output;
948
949 size = Tcl_GetCharLength(value);
950 result = PyUnicode_FromUnicode(NULL, size);
951 if (!result)
952 return NULL;
953 input = Tcl_GetUnicode(value);
954 output = PyUnicode_AS_UNICODE(result);
955 while (size--)
956 *output++ = *input++;
957 return result;
958#else
959 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
960 Tcl_GetCharLength(value));
961#endif
962#else
963 int size;
964 char *c;
965 c = Tcl_GetStringFromObj(value, &size);
966 return PyString_FromStringAndSize(c, size);
967#endif
968 }
969
970 return newPyTclObject(value);
971}
972
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000973/* This mutex synchronizes inter-thread command calls. */
974
975TCL_DECLARE_MUTEX(call_mutex)
976
977typedef struct Tkapp_CallEvent {
978 Tcl_Event ev; /* Must be first */
979 TkappObject *self;
980 PyObject *args;
981 int flags;
982 PyObject **res;
983 PyObject **exc_type, **exc_value, **exc_tb;
984 Tcl_Condition done;
985} Tkapp_CallEvent;
986
987void
988Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +0000989{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000990 int i;
991 for (i = 0; i < objc; i++)
992 Tcl_DecrRefCount(objv[i]);
993 if (objv != objStore)
994 ckfree(FREECAST objv);
995}
Guido van Rossum18468821994-06-20 07:49:28 +0000996
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000997/* Convert Python objects to Tcl objects. This must happen in the
998 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +0000999
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001000static Tcl_Obj**
1001Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1002{
1003 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001004 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001005 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001006 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001007
Guido van Rossum212643f1998-04-29 16:22:14 +00001008 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001009 objv[0] = AsObj(args);
1010 if (objv[0] == 0)
1011 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001012 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001013 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001014 }
1015 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001016 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001017
Guido van Rossum632de272000-03-29 00:19:50 +00001018 if (objc > ARGSZ) {
1019 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1020 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001021 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001022 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001023 goto finally;
1024 }
1025 }
1026
Guido van Rossum632de272000-03-29 00:19:50 +00001027 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001028 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001029 if (v == Py_None) {
1030 objc = i;
1031 break;
1032 }
Guido van Rossum632de272000-03-29 00:19:50 +00001033 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001034 if (!objv[i]) {
1035 /* Reset objc, so it attempts to clear
1036 objects only up to i. */
1037 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001038 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001039 }
Guido van Rossum632de272000-03-29 00:19:50 +00001040 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001041 }
1042 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001043 *pobjc = objc;
1044 return objv;
1045finally:
1046 Tkapp_CallDeallocArgs(objv, objStore, objc);
1047 return NULL;
1048}
Guido van Rossum212643f1998-04-29 16:22:14 +00001049
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001050/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001051
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001052static PyObject*
1053Tkapp_CallResult(TkappObject *self)
1054{
1055 PyObject *res = NULL;
1056 if(self->wantobjects) {
1057 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001058 /* Not sure whether the IncrRef is necessary, but something
1059 may overwrite the interpreter result while we are
1060 converting it. */
1061 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001062 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001063 Tcl_DecrRefCount(value);
1064 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001065 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001066 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001067
Guido van Rossum990f5c62000-05-04 15:07:16 +00001068 /* If the result contains any bytes with the top bit set,
1069 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001070#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001071 while (*p != '\0') {
1072 if (*p & 0x80)
1073 break;
1074 p++;
1075 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001076
Guido van Rossum990f5c62000-05-04 15:07:16 +00001077 if (*p == '\0')
1078 res = PyString_FromStringAndSize(s, (int)(p-s));
1079 else {
1080 /* Convert UTF-8 to Unicode string */
1081 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001082 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1083 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001084 PyErr_Clear();
1085 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001086 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001087 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001088#else
1089 p = strchr(p, '\0');
1090 res = PyString_FromStringAndSize(s, (int)(p-s));
1091#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001092 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001093 return res;
1094}
Guido van Rossum632de272000-03-29 00:19:50 +00001095
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001096/* Tkapp_CallProc is the event procedure that is executed in the context of
1097 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1098 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001099
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001100static int
1101Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1102{
1103 Tcl_Obj *objStore[ARGSZ];
1104 Tcl_Obj **objv;
1105 int objc;
1106 int i;
1107 ENTER_PYTHON
1108 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1109 if (!objv) {
1110 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1111 *(e->res) = NULL;
1112 }
1113 LEAVE_PYTHON
1114 if (!objv)
1115 goto done;
1116 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1117 ENTER_PYTHON
1118 if (i == TCL_ERROR) {
1119 *(e->res) = NULL;
1120 *(e->exc_type) = NULL;
1121 *(e->exc_tb) = NULL;
1122 *(e->exc_value) = PyObject_CallFunction(
1123 Tkinter_TclError, "s",
1124 Tcl_GetStringResult(e->self->interp));
1125 }
1126 else {
1127 *(e->res) = Tkapp_CallResult(e->self);
1128 }
1129 LEAVE_PYTHON
1130 done:
1131 /* Wake up calling thread. */
1132 Tcl_MutexLock(&call_mutex);
1133 Tcl_ConditionNotify(&e->done);
1134 Tcl_MutexUnlock(&call_mutex);
1135 return 1;
1136}
1137
1138/* This is the main entry point for calling a Tcl command.
1139 It supports three cases, with regard to threading:
1140 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1141 the context of the calling thread.
1142 2. Tcl is threaded, caller of the command is in the interpreter thread:
1143 Execute the command in the calling thread. Since the Tcl lock will
1144 not be used, we can merge that with case 1.
1145 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1146 the interpreter thread. Allocation of Tcl objects needs to occur in the
1147 interpreter thread, so we ship the PyObject* args to the target thread,
1148 and perform processing there. */
1149
1150static PyObject *
1151Tkapp_Call(PyObject *_self, PyObject *args)
1152{
1153 Tcl_Obj *objStore[ARGSZ];
1154 Tcl_Obj **objv = NULL;
1155 int objc, i;
1156 PyObject *res = NULL;
1157 TkappObject *self = (TkappObject*)_self;
1158 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1159 int flags = TCL_EVAL_DIRECT;
1160
1161 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1162 /* We cannot call the command directly. Instead, we must
1163 marshal the parameters to the interpreter thread. */
1164 Tkapp_CallEvent *ev;
1165 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001166 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001167 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001168 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1169 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1170 ev->self = self;
1171 ev->args = args;
1172 ev->res = &res;
1173 ev->exc_type = &exc_type;
1174 ev->exc_value = &exc_value;
1175 ev->exc_tb = &exc_tb;
1176 ev->done = (Tcl_Condition)0;
1177
1178 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1179
1180 if (res == NULL) {
1181 if (exc_type)
1182 PyErr_Restore(exc_type, exc_value, exc_tb);
1183 else
1184 PyErr_SetObject(Tkinter_TclError, exc_value);
1185 }
1186 }
1187 else {
1188
1189 objv = Tkapp_CallArgs(args, objStore, &objc);
1190 if (!objv)
1191 return NULL;
1192
1193 ENTER_TCL
1194
1195 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1196
1197 ENTER_OVERLAP
1198
1199 if (i == TCL_ERROR)
1200 Tkinter_Error(_self);
1201 else
1202 res = Tkapp_CallResult(self);
1203
1204 LEAVE_OVERLAP_TCL
1205
1206 Tkapp_CallDeallocArgs(objv, objStore, objc);
1207 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001208 return res;
1209}
1210
1211
1212static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001213Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001214{
Guido van Rossum212643f1998-04-29 16:22:14 +00001215 /* Could do the same here as for Tkapp_Call(), but this is not used
1216 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1217 way for the user to do what all its Global* variants do (save and
1218 reset the scope pointer, call the local version, restore the saved
1219 scope pointer). */
1220
Guido van Rossum62320c91998-06-15 04:36:09 +00001221 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001222 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001223
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001224 CHECK_TCL_APPARTMENT;
1225
Guido van Rossum62320c91998-06-15 04:36:09 +00001226 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001227 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001228 int err;
1229 ENTER_TCL
1230 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001231 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001232 if (err == TCL_ERROR)
1233 res = Tkinter_Error(self);
1234 else
1235 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001236 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001237 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001238 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001239
1240 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001241}
1242
1243static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001244Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001245{
Barry Warsawfa701a81997-01-16 00:15:11 +00001246 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001247 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001248 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001249
Guido van Rossum43713e52000-02-29 13:59:29 +00001250 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001251 return NULL;
1252
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001253 CHECK_TCL_APPARTMENT;
1254
Guido van Rossum00d93061998-05-28 23:06:38 +00001255 ENTER_TCL
1256 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001257 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001258 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001259 res = Tkinter_Error(self);
1260 else
1261 res = PyString_FromString(Tkapp_Result(self));
1262 LEAVE_OVERLAP_TCL
1263 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001264}
1265
1266static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001267Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001268{
Barry Warsawfa701a81997-01-16 00:15:11 +00001269 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001270 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001271 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001272
Guido van Rossum43713e52000-02-29 13:59:29 +00001273 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001274 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001275
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001276 CHECK_TCL_APPARTMENT;
1277
Guido van Rossum00d93061998-05-28 23:06:38 +00001278 ENTER_TCL
1279 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001280 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001281 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001282 res = Tkinter_Error(self);
1283 else
1284 res = PyString_FromString(Tkapp_Result(self));
1285 LEAVE_OVERLAP_TCL
1286 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001287}
1288
1289static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001290Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001291{
Barry Warsawfa701a81997-01-16 00:15:11 +00001292 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001293 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001294 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001295
Guido van Rossum43713e52000-02-29 13:59:29 +00001296 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001297 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001298
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001299 CHECK_TCL_APPARTMENT;
1300
Guido van Rossum00d93061998-05-28 23:06:38 +00001301 ENTER_TCL
1302 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001303 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001304 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001305 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001306
Guido van Rossum62320c91998-06-15 04:36:09 +00001307 else
1308 res = PyString_FromString(Tkapp_Result(self));
1309 LEAVE_OVERLAP_TCL
1310 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001311}
1312
1313static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001314Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001315{
Barry Warsawfa701a81997-01-16 00:15:11 +00001316 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001317 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001318 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001319
Guido van Rossum35d43371997-08-02 00:09:09 +00001320 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001321 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001322
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001323 CHECK_TCL_APPARTMENT;
1324
Guido van Rossum00d93061998-05-28 23:06:38 +00001325 ENTER_TCL
1326 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001327 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001328 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001329 res = Tkinter_Error(self);
1330 else
1331 res = PyString_FromString(Tkapp_Result(self));
1332 LEAVE_OVERLAP_TCL
1333 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001334}
1335
1336static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001337Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001338{
Barry Warsawfa701a81997-01-16 00:15:11 +00001339 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001340
Guido van Rossum43713e52000-02-29 13:59:29 +00001341 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001342 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001343 CHECK_TCL_APPARTMENT;
1344
Guido van Rossum00d93061998-05-28 23:06:38 +00001345 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001346 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001347 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001348
Barry Warsawfa701a81997-01-16 00:15:11 +00001349 Py_INCREF(Py_None);
1350 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001351}
1352
Barry Warsawfa701a81997-01-16 00:15:11 +00001353
1354
Guido van Rossum18468821994-06-20 07:49:28 +00001355/** Tcl Variable **/
1356
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001357TCL_DECLARE_MUTEX(var_mutex)
1358
Martin v. Löwis5b177f12002-12-30 18:14:15 +00001359typedef CONST84_RETURN char* (*EventFunc1)(Tcl_Interp*, CONST char*, int);
1360typedef CONST84_RETURN char* (*EventFunc2)(Tcl_Interp*, CONST char*, CONST char*, int);
1361typedef CONST84_RETURN char* (*EventFunc3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001362typedef struct VarEvent {
1363 Tcl_Event ev; /* must be first */
1364 TkappObject *self;
1365 char* arg1;
1366 char* arg2;
1367 char* arg3;
1368 int flags;
1369 EventFunc1 func1;
1370 EventFunc2 func2;
1371 EventFunc3 func3;
1372 PyObject **res;
1373 PyObject **exc;
1374 Tcl_Condition cond;
1375 int coderesult;
1376} VarEvent;
1377
1378static const char*
1379var_perform(VarEvent *ev)
1380{
1381 if (!ev->arg2 && !ev->arg2)
1382 return ev->func1(ev->self->interp, ev->arg1, ev->flags);
1383 if (!ev->arg3)
1384 return ev->func2(ev->self->interp, ev->arg1,
1385 ev->arg2, ev->flags);
1386 return ev->func3(ev->self->interp, ev->arg1, ev->arg2,
1387 ev->arg3, ev->flags);
1388}
1389
1390static void
1391var_fill_result(VarEvent *ev, const char* res)
1392{
1393 if (ev->coderesult) {
1394 if ((int)res != TCL_ERROR) {
1395 Py_INCREF(Py_None);
1396 *(ev->res) = Py_None;
1397 return;
1398 }
1399 }
1400 else if (res) {
1401 *(ev->res) = PyString_FromString(res);
1402 return;
1403 }
1404
1405 *(ev->res) = NULL;
1406 *(ev->exc) = PyObject_CallFunction(
1407 Tkinter_TclError, "s",
1408 Tcl_GetStringResult(ev->self->interp));
1409
1410}
1411
1412static int
1413var_proc(VarEvent* ev, int flags)
1414{
1415 const char *result = var_perform(ev);
1416 ENTER_PYTHON
1417 var_fill_result(ev, result);
1418 Tcl_MutexLock(&var_mutex);
1419 Tcl_ConditionNotify(&ev->cond);
1420 Tcl_MutexUnlock(&var_mutex);
1421 LEAVE_PYTHON
1422 return 1;
1423}
1424
1425static PyObject*
1426var_invoke(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
1427 EventFunc1 func1, EventFunc2 func2, EventFunc3 func3,
1428 int coderesult)
1429{
1430 VarEvent _ev;
1431 TkappObject *self = (TkappObject*)_self;
1432 VarEvent *ev = self->threaded ?
1433 (VarEvent*)ckalloc(sizeof(VarEvent)) : &_ev;
1434 PyObject *res, *exc;
1435
1436 ev->self = self;
1437 ev->arg1 = arg1;
1438 ev->arg2 = arg2;
1439 ev->arg3 = arg3;
1440 ev->flags = flags;
1441 ev->func1 = func1;
1442 ev->func2 = func2;
1443 ev->func3 = func3;
1444 ev->coderesult = coderesult;
1445 ev->res = &res;
1446 ev->exc = &exc;
1447 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1448 /* The current thread is not the interpreter thread. Marshal
1449 the call to the interpreter thread, then wait for
1450 completion. */
1451
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001452 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001453 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001454 ev->cond = NULL;
1455 ev->ev.proc = (Tcl_EventProc*)var_proc;
1456 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1457 }
1458 else {
1459 /* Tcl is not threaded, or this is the interpreter thread. To
1460 perform the call, we must hold the TCL lock. To receive the
1461 results, we must also hold the Python lock. */
1462 const char *result;
1463 ENTER_TCL
1464 result = var_perform(ev);
1465 ENTER_OVERLAP
1466 var_fill_result(ev, result);
1467 LEAVE_OVERLAP_TCL
1468 }
1469 if (!res) {
1470 PyErr_SetObject(Tkinter_TclError, exc);
1471 return NULL;
1472 }
1473 return res;
1474}
1475
1476static PyObject*
1477var_invoke2(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
Martin v. Löwis5b177f12002-12-30 18:14:15 +00001478 int (*func1)(Tcl_Interp*, CONST char*, int),
1479 int (*func2)(Tcl_Interp*, CONST char*, CONST char*, int),
1480 int (*func3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001481{
1482 return var_invoke(_self, arg1, arg2, arg3, flags,
1483 (EventFunc1)func1, (EventFunc2)func2,
1484 (EventFunc3)func3, 1);
1485}
1486
Guido van Rossum18468821994-06-20 07:49:28 +00001487static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001488SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001489{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001490 char *name1, *name2, *s;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001491 PyObject *res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001492 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +00001493 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +00001494
Guido van Rossum62320c91998-06-15 04:36:09 +00001495 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +00001496 if (!tmp)
1497 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001498
Guido van Rossum43713e52000-02-29 13:59:29 +00001499 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001500 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +00001501 s = AsString(newValue, tmp);
Guido van Rossum2834b972000-10-06 16:58:26 +00001502 if (s == NULL)
1503 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001504 res = var_invoke(self, name1, s, NULL, flags,
1505 NULL, Tcl_SetVar, NULL, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001506 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001507 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001508 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001509 if (PyArg_ParseTuple(args, "ssO:setvar",
1510 &name1, &name2, &newValue)) {
1511 s = AsString(newValue, tmp);
1512 if (s == NULL)
1513 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001514 res = var_invoke(self, name1, name2, s, flags,
1515 NULL, NULL, Tcl_SetVar2, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001516 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001517 else {
Guido van Rossum00d93061998-05-28 23:06:38 +00001518 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +00001519 return NULL;
1520 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001521 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001522 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +00001523
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001524 if (!res)
1525 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001526
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001527 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001528 Py_INCREF(Py_None);
1529 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001530}
1531
1532static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001533Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001534{
Barry Warsawfa701a81997-01-16 00:15:11 +00001535 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001536}
1537
1538static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001539Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001540{
Barry Warsawfa701a81997-01-16 00:15:11 +00001541 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001542}
1543
Barry Warsawfa701a81997-01-16 00:15:11 +00001544
1545
Guido van Rossum18468821994-06-20 07:49:28 +00001546static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001547GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001548{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001549 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001550 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001551
Guido van Rossum43713e52000-02-29 13:59:29 +00001552 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001553 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001554
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001555 res = var_invoke(self, name1, name2, NULL, flags,
1556 Tcl_GetVar, Tcl_GetVar2, NULL, 0);
Guido van Rossum62320c91998-06-15 04:36:09 +00001557 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001558}
1559
1560static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001561Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001562{
Barry Warsawfa701a81997-01-16 00:15:11 +00001563 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001564}
1565
1566static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001567Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001568{
Barry Warsawfa701a81997-01-16 00:15:11 +00001569 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001570}
1571
Barry Warsawfa701a81997-01-16 00:15:11 +00001572
1573
Guido van Rossum18468821994-06-20 07:49:28 +00001574static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001575UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001576{
Guido van Rossum35d43371997-08-02 00:09:09 +00001577 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001578 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001579
Guido van Rossum43713e52000-02-29 13:59:29 +00001580 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001581 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001582
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001583 res = var_invoke2(self, name1, name2, NULL, flags,
1584 Tcl_UnsetVar, Tcl_UnsetVar2, NULL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001585 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001586}
1587
1588static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001589Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001590{
Barry Warsawfa701a81997-01-16 00:15:11 +00001591 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001592}
1593
1594static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001595Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001596{
Barry Warsawfa701a81997-01-16 00:15:11 +00001597 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001598}
1599
Barry Warsawfa701a81997-01-16 00:15:11 +00001600
1601
Guido van Rossum18468821994-06-20 07:49:28 +00001602/** Tcl to Python **/
1603
1604static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001605Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001606{
Barry Warsawfa701a81997-01-16 00:15:11 +00001607 char *s;
1608 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001609
Martin v. Löwisffad6332002-11-26 09:28:05 +00001610 if (PyTuple_Size(args) == 1) {
1611 PyObject* o = PyTuple_GetItem(args, 0);
1612 if (PyInt_Check(o)) {
1613 Py_INCREF(o);
1614 return o;
1615 }
1616 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001617 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001618 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001619 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001620 return Tkinter_Error(self);
1621 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001622}
1623
1624static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001625Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001626{
Barry Warsawfa701a81997-01-16 00:15:11 +00001627 char *s;
1628 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001629
Martin v. Löwisffad6332002-11-26 09:28:05 +00001630 if (PyTuple_Size(args) == 1) {
1631 PyObject *o = PyTuple_GetItem(args, 0);
1632 if (PyFloat_Check(o)) {
1633 Py_INCREF(o);
1634 return o;
1635 }
1636 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001637 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001638 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001639 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001640 return Tkinter_Error(self);
1641 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001642}
1643
1644static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001645Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001646{
Barry Warsawfa701a81997-01-16 00:15:11 +00001647 char *s;
1648 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001649
Martin v. Löwisffad6332002-11-26 09:28:05 +00001650 if (PyTuple_Size(args) == 1) {
1651 PyObject *o = PyTuple_GetItem(args, 0);
1652 if (PyInt_Check(o)) {
1653 Py_INCREF(o);
1654 return o;
1655 }
1656 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001657 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001658 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001659 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1660 return Tkinter_Error(self);
Barry Warsawfa701a81997-01-16 00:15:11 +00001661 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001662}
1663
1664static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001665Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001666{
Barry Warsawfa701a81997-01-16 00:15:11 +00001667 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001668 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001669 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001670
Guido van Rossum43713e52000-02-29 13:59:29 +00001671 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001672 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001673
1674 CHECK_TCL_APPARTMENT;
1675
Guido van Rossum00d93061998-05-28 23:06:38 +00001676 ENTER_TCL
1677 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001678 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001679 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001680 res = Tkinter_Error(self);
1681 else
1682 res = Py_BuildValue("s", Tkapp_Result(self));
1683 LEAVE_OVERLAP_TCL
1684 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001685}
1686
1687static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001688Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001689{
Barry Warsawfa701a81997-01-16 00:15:11 +00001690 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001691 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001692 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001693 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001694
Guido van Rossum43713e52000-02-29 13:59:29 +00001695 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001696 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001697
1698 CHECK_TCL_APPARTMENT;
1699
Guido van Rossum00d93061998-05-28 23:06:38 +00001700 ENTER_TCL
1701 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001702 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001703 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001704 res = Tkinter_Error(self);
1705 else
1706 res = Py_BuildValue("l", v);
1707 LEAVE_OVERLAP_TCL
1708 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001709}
1710
1711static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001712Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001713{
Barry Warsawfa701a81997-01-16 00:15:11 +00001714 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001715 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001716 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001717 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001718
Guido van Rossum43713e52000-02-29 13:59:29 +00001719 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001720 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001721 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001722 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001723 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001724 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001725 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001726 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001727 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001728 res = Tkinter_Error(self);
1729 else
1730 res = Py_BuildValue("d", v);
1731 LEAVE_OVERLAP_TCL
1732 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001733}
1734
1735static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001736Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001737{
Barry Warsawfa701a81997-01-16 00:15:11 +00001738 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001739 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001740 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001741 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001742
Guido van Rossum43713e52000-02-29 13:59:29 +00001743 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001744 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001745 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001746 ENTER_TCL
1747 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001748 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001749 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001750 res = Tkinter_Error(self);
1751 else
1752 res = Py_BuildValue("i", v);
1753 LEAVE_OVERLAP_TCL
1754 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001755}
1756
Barry Warsawfa701a81997-01-16 00:15:11 +00001757
1758
Guido van Rossum18468821994-06-20 07:49:28 +00001759static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001760Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001761{
Barry Warsawfa701a81997-01-16 00:15:11 +00001762 char *list;
1763 int argc;
1764 char **argv;
1765 PyObject *v;
1766 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001767
Martin v. Löwisffad6332002-11-26 09:28:05 +00001768 if (PyTuple_Size(args) == 1) {
1769 v = PyTuple_GetItem(args, 0);
1770 if (PyTuple_Check(v)) {
1771 Py_INCREF(v);
1772 return v;
1773 }
1774 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001775 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001776 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001777
Barry Warsawfa701a81997-01-16 00:15:11 +00001778 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1779 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001780
Barry Warsawfa701a81997-01-16 00:15:11 +00001781 if (!(v = PyTuple_New(argc)))
1782 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001783
Barry Warsawfa701a81997-01-16 00:15:11 +00001784 for (i = 0; i < argc; i++) {
1785 PyObject *s = PyString_FromString(argv[i]);
1786 if (!s || PyTuple_SetItem(v, i, s)) {
1787 Py_DECREF(v);
1788 v = NULL;
1789 goto finally;
1790 }
1791 }
Guido van Rossum18468821994-06-20 07:49:28 +00001792
Barry Warsawfa701a81997-01-16 00:15:11 +00001793 finally:
1794 ckfree(FREECAST argv);
1795 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001796}
1797
1798static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001799Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001800{
Barry Warsawfa701a81997-01-16 00:15:11 +00001801 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001802
Martin v. Löwisffad6332002-11-26 09:28:05 +00001803 if (PyTuple_Size(args) == 1) {
1804 PyObject* o = PyTuple_GetItem(args, 0);
1805 if (PyTuple_Check(o)) {
1806 o = SplitObj(o);
1807 return o;
1808 }
1809 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001810 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001811 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001812 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001813}
1814
1815static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001816Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001817{
Barry Warsawfa701a81997-01-16 00:15:11 +00001818 char *s = Merge(args);
1819 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001820
Barry Warsawfa701a81997-01-16 00:15:11 +00001821 if (s) {
1822 res = PyString_FromString(s);
1823 ckfree(s);
1824 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001825
1826 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001827}
1828
Barry Warsawfa701a81997-01-16 00:15:11 +00001829
1830
Guido van Rossum18468821994-06-20 07:49:28 +00001831/** Tcl Command **/
1832
Guido van Rossum00d93061998-05-28 23:06:38 +00001833/* Client data struct */
1834typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001835 PyObject *self;
1836 PyObject *func;
1837} PythonCmd_ClientData;
1838
1839static int
Fred Drake509d79a2000-07-08 04:04:38 +00001840PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001841{
1842 errorInCmd = 1;
1843 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1844 LEAVE_PYTHON
1845 return TCL_ERROR;
1846}
1847
Guido van Rossum18468821994-06-20 07:49:28 +00001848/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001849 * function or method.
1850 */
Guido van Rossum18468821994-06-20 07:49:28 +00001851static int
Fred Drake509d79a2000-07-08 04:04:38 +00001852PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001853{
Guido van Rossum00d93061998-05-28 23:06:38 +00001854 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001855 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001856 int i, rv;
1857 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001858
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001859 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001860
Barry Warsawfa701a81997-01-16 00:15:11 +00001861 /* TBD: no error checking here since we know, via the
1862 * Tkapp_CreateCommand() that the client data is a two-tuple
1863 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001864 self = data->self;
1865 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001866
Barry Warsawfa701a81997-01-16 00:15:11 +00001867 /* Create argument list (argv1, ..., argvN) */
1868 if (!(arg = PyTuple_New(argc - 1)))
1869 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001870
Barry Warsawfa701a81997-01-16 00:15:11 +00001871 for (i = 0; i < (argc - 1); i++) {
1872 PyObject *s = PyString_FromString(argv[i + 1]);
1873 if (!s || PyTuple_SetItem(arg, i, s)) {
1874 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001875 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001876 }
1877 }
1878 res = PyEval_CallObject(func, arg);
1879 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001880
Barry Warsawfa701a81997-01-16 00:15:11 +00001881 if (res == NULL)
1882 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001883
Barry Warsawfa701a81997-01-16 00:15:11 +00001884 if (!(tmp = PyList_New(0))) {
1885 Py_DECREF(res);
1886 return PythonCmd_Error(interp);
1887 }
1888
Guido van Rossum2834b972000-10-06 16:58:26 +00001889 s = AsString(res, tmp);
1890 if (s == NULL) {
1891 rv = PythonCmd_Error(interp);
1892 }
1893 else {
1894 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1895 rv = TCL_OK;
1896 }
1897
Barry Warsawfa701a81997-01-16 00:15:11 +00001898 Py_DECREF(res);
1899 Py_DECREF(tmp);
1900
Guido van Rossum00d93061998-05-28 23:06:38 +00001901 LEAVE_PYTHON
1902
Guido van Rossum2834b972000-10-06 16:58:26 +00001903 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001904}
1905
1906static void
Fred Drake509d79a2000-07-08 04:04:38 +00001907PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001908{
Guido van Rossum00d93061998-05-28 23:06:38 +00001909 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1910
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001911 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001912 Py_XDECREF(data->self);
1913 Py_XDECREF(data->func);
1914 PyMem_DEL(data);
1915 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001916}
1917
Barry Warsawfa701a81997-01-16 00:15:11 +00001918
1919
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001920
1921TCL_DECLARE_MUTEX(command_mutex)
1922
1923typedef struct CommandEvent{
1924 Tcl_Event ev;
1925 Tcl_Interp* interp;
1926 char *name;
1927 int create;
1928 int *status;
1929 ClientData *data;
1930 Tcl_Condition done;
1931} CommandEvent;
1932
1933static int
1934Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001935{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001936 if (ev->create)
1937 *ev->status = Tcl_CreateCommand(
1938 ev->interp, ev->name, PythonCmd,
1939 ev->data, PythonCmdDelete) == NULL;
1940 else
1941 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1942 Tcl_MutexLock(&command_mutex);
1943 Tcl_ConditionNotify(&ev->done);
1944 Tcl_MutexUnlock(&command_mutex);
1945 return 1;
1946}
1947
1948static PyObject *
1949Tkapp_CreateCommand(PyObject *_self, PyObject *args)
1950{
1951 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001952 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001953 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00001954 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001955 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001956
Guido van Rossum43713e52000-02-29 13:59:29 +00001957 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00001958 return NULL;
1959 if (!PyCallable_Check(func)) {
1960 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00001961 return NULL;
1962 }
Guido van Rossum18468821994-06-20 07:49:28 +00001963
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001964 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001965 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001966 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001967
Guido van Rossum00d93061998-05-28 23:06:38 +00001968 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00001969 if (!data)
1970 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001971 Py_XINCREF(self);
1972 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001973 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001974 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001975
1976 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1977 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
1978 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
1979 ev->interp = self->interp;
1980 ev->create = 1;
1981 ev->name = cmdName;
1982 ev->data = (ClientData)data;
1983 ev->status = &err;
1984 ev->done = NULL;
1985 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
1986 }
1987 else {
1988 ENTER_TCL
1989 err = Tcl_CreateCommand(
1990 Tkapp_Interp(self), cmdName, PythonCmd,
1991 (ClientData)data, PythonCmdDelete) == NULL;
1992 LEAVE_TCL
1993 }
1994 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001995 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00001996 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00001997 return NULL;
1998 }
Guido van Rossum18468821994-06-20 07:49:28 +00001999
Barry Warsawfa701a81997-01-16 00:15:11 +00002000 Py_INCREF(Py_None);
2001 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002002}
2003
Barry Warsawfa701a81997-01-16 00:15:11 +00002004
2005
Guido van Rossum18468821994-06-20 07:49:28 +00002006static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002007Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002008{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002009 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002010 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002011 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002012
Guido van Rossum43713e52000-02-29 13:59:29 +00002013 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002014 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002015 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2016 CommandEvent *ev;
2017 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2018 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2019 ev->interp = self->interp;
2020 ev->create = 0;
2021 ev->name = cmdName;
2022 ev->status = &err;
2023 ev->done = NULL;
2024 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2025 &command_mutex);
2026 }
2027 else {
2028 ENTER_TCL
2029 err = Tcl_DeleteCommand(self->interp, cmdName);
2030 LEAVE_TCL
2031 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002032 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002033 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2034 return NULL;
2035 }
2036 Py_INCREF(Py_None);
2037 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002038}
2039
Barry Warsawfa701a81997-01-16 00:15:11 +00002040
2041
Guido van Rossum00d93061998-05-28 23:06:38 +00002042#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002043/** File Handler **/
2044
Guido van Rossum00d93061998-05-28 23:06:38 +00002045typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002046 PyObject *func;
2047 PyObject *file;
2048 int id;
2049 struct _fhcdata *next;
2050} FileHandler_ClientData;
2051
2052static FileHandler_ClientData *HeadFHCD;
2053
2054static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002055NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002056{
2057 FileHandler_ClientData *p;
2058 p = PyMem_NEW(FileHandler_ClientData, 1);
2059 if (p != NULL) {
2060 Py_XINCREF(func);
2061 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002062 p->func = func;
2063 p->file = file;
2064 p->id = id;
2065 p->next = HeadFHCD;
2066 HeadFHCD = p;
2067 }
2068 return p;
2069}
2070
2071static void
Fred Drake509d79a2000-07-08 04:04:38 +00002072DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002073{
2074 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002075
2076 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002077 while ((p = *pp) != NULL) {
2078 if (p->id == id) {
2079 *pp = p->next;
2080 Py_XDECREF(p->func);
2081 Py_XDECREF(p->file);
2082 PyMem_DEL(p);
2083 }
2084 else
2085 pp = &p->next;
2086 }
2087}
2088
Guido van Rossuma597dde1995-01-10 20:56:29 +00002089static void
Fred Drake509d79a2000-07-08 04:04:38 +00002090FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002091{
Guido van Rossum00d93061998-05-28 23:06:38 +00002092 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002093 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002094
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002095 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002096 func = data->func;
2097 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002098
Barry Warsawfa701a81997-01-16 00:15:11 +00002099 arg = Py_BuildValue("(Oi)", file, (long) mask);
2100 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002101 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002102
2103 if (res == NULL) {
2104 errorInCmd = 1;
2105 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2106 }
2107 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002108 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002109}
2110
Guido van Rossum18468821994-06-20 07:49:28 +00002111static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002112Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2113 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002114{
Guido van Rossum00d93061998-05-28 23:06:38 +00002115 FileHandler_ClientData *data;
2116 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002117 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002118
Guido van Rossum2834b972000-10-06 16:58:26 +00002119 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2120 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002121 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002122 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002123 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002124 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002125 return NULL;
2126 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002127 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002128 return NULL;
2129 }
2130
Guido van Rossuma80649b2000-03-28 20:07:05 +00002131 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002132 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002133 return NULL;
2134
Barry Warsawfa701a81997-01-16 00:15:11 +00002135 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002136 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002137 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002138 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002139 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002140 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002141}
2142
2143static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002144Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002145{
Barry Warsawfa701a81997-01-16 00:15:11 +00002146 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002147 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002148
Guido van Rossum43713e52000-02-29 13:59:29 +00002149 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002150 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002151 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002152 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002153 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002154 return NULL;
2155
Guido van Rossuma80649b2000-03-28 20:07:05 +00002156 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002157
Barry Warsawfa701a81997-01-16 00:15:11 +00002158 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002159 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002160 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002161 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002162 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002163 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002164}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002165#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002166
Barry Warsawfa701a81997-01-16 00:15:11 +00002167
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002168/**** Tktt Object (timer token) ****/
2169
Jeremy Hylton938ace62002-07-17 16:30:39 +00002170static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002171
Guido van Rossum00d93061998-05-28 23:06:38 +00002172typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002173 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002174 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002175 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002176} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002177
2178static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002179Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002180{
Barry Warsawfa701a81997-01-16 00:15:11 +00002181 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002182 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002183
Guido van Rossum43713e52000-02-29 13:59:29 +00002184 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002185 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002186 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002187 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002188 v->token = NULL;
2189 }
2190 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002191 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002192 Py_DECREF(func);
2193 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002194 }
2195 Py_INCREF(Py_None);
2196 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002197}
2198
2199static PyMethodDef Tktt_methods[] =
2200{
Neal Norwitzb0493252002-03-31 14:44:22 +00002201 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002202 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002203};
2204
2205static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002206Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002207{
Barry Warsawfa701a81997-01-16 00:15:11 +00002208 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002209
Guido van Rossumb18618d2000-05-03 23:44:39 +00002210 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002211 if (v == NULL)
2212 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002213
Guido van Rossum00d93061998-05-28 23:06:38 +00002214 Py_INCREF(func);
2215 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002216 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002217
2218 /* Extra reference, deleted when called or when handler is deleted */
2219 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002220 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002221}
2222
2223static void
Fred Drake509d79a2000-07-08 04:04:38 +00002224Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002225{
Guido van Rossum00d93061998-05-28 23:06:38 +00002226 TkttObject *v = (TkttObject *)self;
2227 PyObject *func = v->func;
2228
2229 Py_XDECREF(func);
2230
Guido van Rossumb18618d2000-05-03 23:44:39 +00002231 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002232}
2233
Guido van Rossum597ac201998-05-12 14:36:19 +00002234static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002235Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002236{
Barry Warsawfa701a81997-01-16 00:15:11 +00002237 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002238 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002239
Tim Peters885d4572001-11-28 20:27:42 +00002240 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002241 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002242 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002243}
2244
2245static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002246Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002247{
Barry Warsawfa701a81997-01-16 00:15:11 +00002248 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002249}
2250
2251static PyTypeObject Tktt_Type =
2252{
Guido van Rossum35d43371997-08-02 00:09:09 +00002253 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002254 0, /*ob_size */
2255 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002256 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002257 0, /*tp_itemsize */
2258 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002259 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002260 Tktt_GetAttr, /*tp_getattr */
2261 0, /*tp_setattr */
2262 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002263 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002264 0, /*tp_as_number */
2265 0, /*tp_as_sequence */
2266 0, /*tp_as_mapping */
2267 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002268};
2269
Barry Warsawfa701a81997-01-16 00:15:11 +00002270
2271
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002272/** Timer Handler **/
2273
2274static void
Fred Drake509d79a2000-07-08 04:04:38 +00002275TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002276{
Guido van Rossum00d93061998-05-28 23:06:38 +00002277 TkttObject *v = (TkttObject *)clientData;
2278 PyObject *func = v->func;
2279 PyObject *res;
2280
2281 if (func == NULL)
2282 return;
2283
2284 v->func = NULL;
2285
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002286 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002287
2288 res = PyEval_CallObject(func, NULL);
2289 Py_DECREF(func);
2290 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002291
Barry Warsawfa701a81997-01-16 00:15:11 +00002292 if (res == NULL) {
2293 errorInCmd = 1;
2294 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2295 }
2296 else
2297 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002298
2299 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002300}
2301
2302static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002303Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002304{
Barry Warsawfa701a81997-01-16 00:15:11 +00002305 int milliseconds;
2306 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002307 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002308
Guido van Rossum2834b972000-10-06 16:58:26 +00002309 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2310 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002311 return NULL;
2312 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002313 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002314 return NULL;
2315 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002316 v = Tktt_New(func);
2317 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2318 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002319
Guido van Rossum00d93061998-05-28 23:06:38 +00002320 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002321}
2322
Barry Warsawfa701a81997-01-16 00:15:11 +00002323
Guido van Rossum18468821994-06-20 07:49:28 +00002324/** Event Loop **/
2325
Guido van Rossum18468821994-06-20 07:49:28 +00002326static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002327Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002328{
Barry Warsawfa701a81997-01-16 00:15:11 +00002329 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002330 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002331#ifdef WITH_THREAD
2332 PyThreadState *tstate = PyThreadState_Get();
2333#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002334
Guido van Rossum43713e52000-02-29 13:59:29 +00002335 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002336 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002337
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002338 CHECK_TCL_APPARTMENT;
2339
Barry Warsawfa701a81997-01-16 00:15:11 +00002340 quitMainLoop = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002341 self->dispatching = 1;
Barry Warsawfa701a81997-01-16 00:15:11 +00002342 while (Tk_GetNumMainWindows() > threshold &&
2343 !quitMainLoop &&
2344 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002345 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002346 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002347
2348#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002349 if (self->threaded) {
2350 /* Allow other Python threads to run. */
2351 ENTER_TCL
2352 result = Tcl_DoOneEvent(0);
2353 LEAVE_TCL
2354 }
2355 else {
2356 Py_BEGIN_ALLOW_THREADS
2357 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2358 tcl_tstate = tstate;
2359 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2360 tcl_tstate = NULL;
2361 if(tcl_lock)PyThread_release_lock(tcl_lock);
2362 if (result == 0)
2363 Sleep(20);
2364 Py_END_ALLOW_THREADS
2365 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002366#else
2367 result = Tcl_DoOneEvent(0);
2368#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002369
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002370 if (PyErr_CheckSignals() != 0) {
2371 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002372 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002373 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002374 if (result < 0)
2375 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002376 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002377 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002378 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002379
Barry Warsawfa701a81997-01-16 00:15:11 +00002380 if (errorInCmd) {
2381 errorInCmd = 0;
2382 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2383 excInCmd = valInCmd = trbInCmd = NULL;
2384 return NULL;
2385 }
2386 Py_INCREF(Py_None);
2387 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002388}
2389
2390static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002391Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002392{
Guido van Rossum35d43371997-08-02 00:09:09 +00002393 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002394 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002395
Guido van Rossum43713e52000-02-29 13:59:29 +00002396 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002397 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002398 CHECK_TCL_APPARTMENT;
Barry Warsawfa701a81997-01-16 00:15:11 +00002399
Guido van Rossum00d93061998-05-28 23:06:38 +00002400 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002401 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002402 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002403 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002404}
2405
2406static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002407Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002408{
2409
Guido van Rossum43713e52000-02-29 13:59:29 +00002410 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002411 return NULL;
2412
2413 quitMainLoop = 1;
2414 Py_INCREF(Py_None);
2415 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002416}
2417
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002418static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002419Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002420{
2421
Guido van Rossum43713e52000-02-29 13:59:29 +00002422 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002423 return NULL;
2424
2425 return PyInt_FromLong((long)Tkapp_Interp(self));
2426}
2427
Barry Warsawfa701a81997-01-16 00:15:11 +00002428
Martin v. Löwisffad6332002-11-26 09:28:05 +00002429static PyObject *
2430Tkapp_WantObjects(PyObject *self, PyObject *args)
2431{
2432
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002433 int wantobjects;
2434 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002435 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002436 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002437
2438 Py_INCREF(Py_None);
2439 return Py_None;
2440}
2441
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002442static PyObject *
2443Tkapp_WillDispatch(PyObject *self, PyObject *args)
2444{
2445
2446 ((TkappObject*)self)->dispatching = 1;
2447
2448 Py_INCREF(Py_None);
2449 return Py_None;
2450}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002451
Barry Warsawfa701a81997-01-16 00:15:11 +00002452
Guido van Rossum18468821994-06-20 07:49:28 +00002453/**** Tkapp Method List ****/
2454
2455static PyMethodDef Tkapp_methods[] =
2456{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002457 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002458 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002459 {"call", Tkapp_Call, METH_OLDARGS},
2460 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2461 {"eval", Tkapp_Eval, METH_VARARGS},
2462 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2463 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2464 {"record", Tkapp_Record, METH_VARARGS},
2465 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2466 {"setvar", Tkapp_SetVar, METH_VARARGS},
2467 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2468 {"getvar", Tkapp_GetVar, METH_VARARGS},
2469 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2470 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2471 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2472 {"getint", Tkapp_GetInt, METH_VARARGS},
2473 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2474 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2475 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2476 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2477 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2478 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2479 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2480 {"split", Tkapp_Split, METH_VARARGS},
2481 {"merge", Tkapp_Merge, METH_OLDARGS},
2482 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2483 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002484#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002485 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2486 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002487#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002488 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2489 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2490 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2491 {"quit", Tkapp_Quit, METH_VARARGS},
2492 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002493 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002494};
2495
Barry Warsawfa701a81997-01-16 00:15:11 +00002496
2497
Guido van Rossum18468821994-06-20 07:49:28 +00002498/**** Tkapp Type Methods ****/
2499
2500static void
Fred Drake509d79a2000-07-08 04:04:38 +00002501Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002502{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002503 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002504 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002505 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002506 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002507 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002508 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002509}
2510
2511static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002512Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002513{
Guido van Rossum35d43371997-08-02 00:09:09 +00002514 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002515}
2516
2517static PyTypeObject Tkapp_Type =
2518{
Guido van Rossum35d43371997-08-02 00:09:09 +00002519 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002520 0, /*ob_size */
2521 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002522 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002523 0, /*tp_itemsize */
2524 Tkapp_Dealloc, /*tp_dealloc */
2525 0, /*tp_print */
2526 Tkapp_GetAttr, /*tp_getattr */
2527 0, /*tp_setattr */
2528 0, /*tp_compare */
2529 0, /*tp_repr */
2530 0, /*tp_as_number */
2531 0, /*tp_as_sequence */
2532 0, /*tp_as_mapping */
2533 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002534};
2535
Barry Warsawfa701a81997-01-16 00:15:11 +00002536
2537
Guido van Rossum18468821994-06-20 07:49:28 +00002538/**** Tkinter Module ****/
2539
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002540typedef struct {
2541 PyObject* tuple;
2542 int size; /* current size */
2543 int maxsize; /* allocated size */
2544} FlattenContext;
2545
2546static int
2547_bump(FlattenContext* context, int size)
2548{
Guido van Rossum2834b972000-10-06 16:58:26 +00002549 /* expand tuple to hold (at least) size new items.
2550 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002551
2552 int maxsize = context->maxsize * 2;
2553
2554 if (maxsize < context->size + size)
2555 maxsize = context->size + size;
2556
2557 context->maxsize = maxsize;
2558
Tim Peters4324aa32001-05-28 22:30:08 +00002559 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002560}
2561
2562static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002563_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002564{
2565 /* add tuple or list to argument tuple (recursively) */
2566
2567 int i, size;
2568
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002569 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002570 PyErr_SetString(PyExc_ValueError,
2571 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002572 return 0;
2573 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002574 size = PyList_GET_SIZE(item);
2575 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002576 if (context->size + size > context->maxsize &&
2577 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002578 return 0;
2579 /* copy items to output tuple */
2580 for (i = 0; i < size; i++) {
2581 PyObject *o = PyList_GET_ITEM(item, i);
2582 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002583 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002584 return 0;
2585 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002586 if (context->size + 1 > context->maxsize &&
2587 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002588 return 0;
2589 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002590 PyTuple_SET_ITEM(context->tuple,
2591 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002592 }
2593 }
2594 } else if (PyTuple_Check(item)) {
2595 /* same, for tuples */
2596 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002597 if (context->size + size > context->maxsize &&
2598 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002599 return 0;
2600 for (i = 0; i < size; i++) {
2601 PyObject *o = PyTuple_GET_ITEM(item, i);
2602 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002603 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002604 return 0;
2605 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002606 if (context->size + 1 > context->maxsize &&
2607 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002608 return 0;
2609 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002610 PyTuple_SET_ITEM(context->tuple,
2611 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002612 }
2613 }
2614 } else {
2615 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2616 return 0;
2617 }
2618 return 1;
2619}
2620
2621static PyObject *
2622Tkinter_Flatten(PyObject* self, PyObject* args)
2623{
2624 FlattenContext context;
2625 PyObject* item;
2626
2627 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2628 return NULL;
2629
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002630 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002631 if (context.maxsize <= 0)
2632 return PyTuple_New(0);
2633
2634 context.tuple = PyTuple_New(context.maxsize);
2635 if (!context.tuple)
2636 return NULL;
2637
2638 context.size = 0;
2639
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002640 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002641 return NULL;
2642
Tim Peters4324aa32001-05-28 22:30:08 +00002643 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002644 return NULL;
2645
2646 return context.tuple;
2647}
2648
Guido van Rossum18468821994-06-20 07:49:28 +00002649static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002650Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002651{
Barry Warsawfa701a81997-01-16 00:15:11 +00002652 char *screenName = NULL;
2653 char *baseName = NULL;
2654 char *className = NULL;
2655 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002656 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002657
Guido van Rossum35d43371997-08-02 00:09:09 +00002658 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002659 if (baseName != NULL)
2660 baseName++;
2661 else
2662 baseName = Py_GetProgramName();
2663 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002664
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002665 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002666 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002667 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002668 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002669
Barry Warsawfa701a81997-01-16 00:15:11 +00002670 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002671 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002672}
2673
2674static PyMethodDef moduleMethods[] =
2675{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002676 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2677 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002678#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002679 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2680 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002681#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002682 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2683 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2684 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2685 {"quit", Tkapp_Quit, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002686 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002687};
2688
Guido van Rossum7bf15641998-05-22 18:28:17 +00002689#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002690
2691static int stdin_ready = 0;
2692
Guido van Rossumad4db171998-06-13 13:56:28 +00002693#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002694static void
Fred Drake509d79a2000-07-08 04:04:38 +00002695MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002696{
2697 stdin_ready = 1;
2698}
Guido van Rossumad4db171998-06-13 13:56:28 +00002699#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002700
Guido van Rossum00d93061998-05-28 23:06:38 +00002701static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002702
Guido van Rossum18468821994-06-20 07:49:28 +00002703static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002704EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002705{
Guido van Rossumad4db171998-06-13 13:56:28 +00002706#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002707 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002708#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002709#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002710 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002711#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002712 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002713 errorInCmd = 0;
2714#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002715 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002716 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002717#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002718 while (!errorInCmd && !stdin_ready) {
2719 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002720#ifdef MS_WINDOWS
2721 if (_kbhit()) {
2722 stdin_ready = 1;
2723 break;
2724 }
2725#endif
2726#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002727 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002728 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002729 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002730
Guido van Rossum00d93061998-05-28 23:06:38 +00002731 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002732
2733 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002734 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002735 if (result == 0)
2736 Sleep(20);
2737 Py_END_ALLOW_THREADS
2738#else
2739 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002740#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002741
2742 if (result < 0)
2743 break;
2744 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002745#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002746 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002747#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002748 if (errorInCmd) {
2749 errorInCmd = 0;
2750 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2751 excInCmd = valInCmd = trbInCmd = NULL;
2752 PyErr_Print();
2753 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002754#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002755 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002756#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002757 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002758}
Guido van Rossum18468821994-06-20 07:49:28 +00002759
Guido van Rossum00d93061998-05-28 23:06:38 +00002760#endif
2761
Guido van Rossum7bf15641998-05-22 18:28:17 +00002762static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002763EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002764{
Guido van Rossum00d93061998-05-28 23:06:38 +00002765#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002766 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002767#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002768 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002769#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002770 PyOS_InputHook = EventHook;
2771 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002772#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002773}
2774
2775static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002776DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002777{
Guido van Rossum00d93061998-05-28 23:06:38 +00002778#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002779 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2780 PyOS_InputHook = NULL;
2781 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002782#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002783}
2784
Barry Warsawfa701a81997-01-16 00:15:11 +00002785
2786/* all errors will be checked in one fell swoop in init_tkinter() */
2787static void
Fred Drake509d79a2000-07-08 04:04:38 +00002788ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002789{
2790 PyObject *v = PyInt_FromLong(val);
2791 if (v) {
2792 PyDict_SetItemString(d, name, v);
2793 Py_DECREF(v);
2794 }
2795}
2796static void
Fred Drake509d79a2000-07-08 04:04:38 +00002797ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002798{
2799 PyObject *v = PyString_FromString(val);
2800 if (v) {
2801 PyDict_SetItemString(d, name, v);
2802 Py_DECREF(v);
2803 }
2804}
2805
2806
Mark Hammond62b1ab12002-07-23 06:31:15 +00002807PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002808init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002809{
Barry Warsawfa701a81997-01-16 00:15:11 +00002810 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002811
Barry Warsawfa701a81997-01-16 00:15:11 +00002812 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002813
2814#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002815 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002816#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002817
Barry Warsawfa701a81997-01-16 00:15:11 +00002818 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002819
Barry Warsawfa701a81997-01-16 00:15:11 +00002820 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00002821 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00002822 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002823
Guido van Rossum35d43371997-08-02 00:09:09 +00002824 ins_long(d, "READABLE", TCL_READABLE);
2825 ins_long(d, "WRITABLE", TCL_WRITABLE);
2826 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2827 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2828 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2829 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2830 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2831 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2832 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002833 ins_string(d, "TK_VERSION", TK_VERSION);
2834 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002835
Guido van Rossum83551bf1997-09-13 00:44:23 +00002836 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002837
2838 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002839 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2840
Martin v. Löwisffad6332002-11-26 09:28:05 +00002841 PyTclObject_Type.ob_type = &PyType_Type;
Jason Tishlerbbe89612002-12-31 20:30:46 +00002842 PyTclObject_Type.tp_getattro = &PyObject_GenericGetAttr;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002843 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002844
2845#ifdef TK_AQUA
2846 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2847 * start waking up. Note that Tcl_FindExecutable will do this, this
2848 * code must be above it! The original warning from
2849 * tkMacOSXAppInit.c is copied below.
2850 *
2851 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2852 * Tcl interpreter for now. It probably should work to do this
2853 * in the other order, but for now it doesn't seem to.
2854 *
2855 */
2856 Tk_MacOSXSetupTkNotifier();
2857#endif
2858
2859
Guido van Rossume187b0e2000-03-27 21:46:29 +00002860 /* This helps the dynamic loader; in Unicode aware Tcl versions
2861 it also helps Tcl find its encodings. */
2862 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00002863
Barry Warsawfa701a81997-01-16 00:15:11 +00002864 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002865 return;
2866
Guido van Rossum43ff8681998-07-14 18:02:13 +00002867#if 0
2868 /* This was not a good idea; through <Destroy> bindings,
2869 Tcl_Finalize() may invoke Python code but at that point the
2870 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002871 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002872#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002873
Jack Jansen34cc5c31995-10-31 16:15:12 +00002874#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002875 /*
2876 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2877 ** Most of the initializations in that routine (toolbox init calls and
2878 ** such) have already been done for us, so we only need these.
2879 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002880 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002881
2882 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00002883#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00002884 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00002885#endif /* GENERATINGCFM */
2886#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00002887}
Guido van Rossum9722ad81995-09-22 23:49:28 +00002888
Guido van Rossumec22c921996-02-25 04:50:29 +00002889
Barry Warsawfa701a81997-01-16 00:15:11 +00002890
Guido van Rossum9722ad81995-09-22 23:49:28 +00002891#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002892
2893/*
Guido van Rossumec22c921996-02-25 04:50:29 +00002894** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002895*/
2896
Guido van Rossum9722ad81995-09-22 23:49:28 +00002897void
2898panic(char * format, ...)
2899{
Barry Warsawfa701a81997-01-16 00:15:11 +00002900 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002901
Barry Warsawfa701a81997-01-16 00:15:11 +00002902 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002903
Guido van Rossum227cf761998-08-05 13:53:32 +00002904 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002905 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002906
Barry Warsawfa701a81997-01-16 00:15:11 +00002907 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002908
Barry Warsawfa701a81997-01-16 00:15:11 +00002909 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00002910}
Jack Jansen40b546d1995-11-14 10:34:45 +00002911
Guido van Rossumec22c921996-02-25 04:50:29 +00002912/*
2913** Pass events to SIOUX before passing them to Tk.
2914*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002915
Guido van Rossumec22c921996-02-25 04:50:29 +00002916static int
Fred Drake509d79a2000-07-08 04:04:38 +00002917PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002918{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002919 WindowPtr frontwin;
2920 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00002921 ** Sioux eats too many events, so we don't pass it everything. We
2922 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002923 ** the Sioux window is frontmost. This means that Tk menus don't work
2924 ** in that case, but at least we can scroll the sioux window.
2925 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2926 ** part of the external interface of Sioux...
2927 */
2928 frontwin = FrontWindow();
2929 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
2930 if (SIOUXHandleOneEvent(eventPtr))
2931 return 0; /* Nothing happened to the Tcl event queue */
2932 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002933 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002934}
2935
Guido van Rossumec22c921996-02-25 04:50:29 +00002936#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002937
2938/*
2939** Additional Mac specific code for dealing with shared libraries.
2940*/
2941
2942#include <Resources.h>
2943#include <CodeFragments.h>
2944
2945static int loaded_from_shlib = 0;
2946static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002947
Jack Jansen34cc5c31995-10-31 16:15:12 +00002948/*
2949** If this module is dynamically loaded the following routine should
2950** be the init routine. It takes care of adding the shared library to
2951** the resource-file chain, so that the tk routines can find their
2952** resources.
2953*/
2954OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002955init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002956{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00002957 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00002958 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002959 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002960 library_fss = *data->fragLocator.u.onDisk.fileSpec;
2961 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002962 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002963 library_fss = *data->fragLocator.u.inSegs.fileSpec;
2964 loaded_from_shlib = 1;
2965 }
2966 return noErr;
2967}
2968
2969/*
2970** Insert the library resources into the search path. Put them after
2971** the resources from the application. Again, we ignore errors.
2972*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002973static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002974mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002975{
2976 if ( !loaded_from_shlib )
2977 return;
2978 (void)FSpOpenResFile(&library_fss, fsRdPerm);
2979}
2980
Guido van Rossumec22c921996-02-25 04:50:29 +00002981#endif /* GENERATINGCFM */
2982#endif /* macintosh */