blob: 112263165237f747ac707fa6635b8f30cde6fb22 [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
Guido van Rossum3e819a71997-08-01 19:29:02 +000060#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
61
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000062#if TKMAJORMINOR < 8002
63#error "Tk older than 8.2 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000064#endif
65
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000066/* Unicode conversion assumes that Tcl_UniChar is two bytes.
67 We cannot test this directly, so we test UTF-8 size instead,
68 expecting that TCL_UTF_MAX is changed if Tcl ever supports
69 either UTF-16 or UCS-4. */
70#if TCL_UTF_MAX != 3
71#error "unsupported Tcl configuration"
72#endif
73
Guido van Rossuma80649b2000-03-28 20:07:05 +000074#if defined(macintosh)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000075/* Sigh, we have to include this to get at the tcl qd pointer */
76#include <tkMac.h>
Guido van Rossum2ea1c941998-04-28 16:12:43 +000077/* And this one we need to clear the menu bar */
78#include <Menus.h>
Guido van Rossum0d2390c1997-08-14 19:57:07 +000079#endif
80
Jack Jansen84c10b12001-07-16 19:32:52 +000081#if !(defined(MS_WINDOWS) || defined(__CYGWIN__) || defined(macintosh))
82/* Mac has it, but it doesn't really work:-( */
Guido van Rossum0d2390c1997-08-14 19:57:07 +000083#define HAVE_CREATEFILEHANDLER
84#endif
85
Guido van Rossum00d93061998-05-28 23:06:38 +000086#ifdef HAVE_CREATEFILEHANDLER
87
88/* Tcl_CreateFileHandler() changed several times; these macros deal with the
89 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
90 Unix, only because Jack added it back); when available on Windows, it only
91 applies to sockets. */
92
Guido van Rossum7bf15641998-05-22 18:28:17 +000093#ifdef MS_WINDOWS
94#define FHANDLETYPE TCL_WIN_SOCKET
95#else
96#define FHANDLETYPE TCL_UNIX_FD
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
100 which uses this to handle Tcl events while the user is typing commands. */
101
102#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000103#define WAIT_FOR_STDIN
104#endif
105
Guido van Rossum00d93061998-05-28 23:06:38 +0000106#endif /* HAVE_CREATEFILEHANDLER */
107
Guido van Rossumad4db171998-06-13 13:56:28 +0000108#ifdef MS_WINDOWS
109#include <conio.h>
110#define WAIT_FOR_STDIN
111#endif
112
Guido van Rossum00d93061998-05-28 23:06:38 +0000113#ifdef WITH_THREAD
114
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000115/* The threading situation is complicated. Tcl is not thread-safe, except
116 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000117 So we need to use a lock around all uses of Tcl. Previously, the Python
118 interpreter lock was used for this. However, this causes problems when
119 other Python threads need to run while Tcl is blocked waiting for events.
120
121 To solve this problem, a separate lock for Tcl is introduced. Holding it
122 is incompatible with holding Python's interpreter lock. The following four
123 macros manipulate both locks together.
124
125 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
126 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
127 that could call an event handler, or otherwise affect the state of a Tcl
128 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000129 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000130 released and the lock for Tcl has been acquired.
131
Guido van Rossum5e977831998-06-15 14:03:52 +0000132 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
133 (For example, when transferring data from the Tcl interpreter result to a
134 Python string object.) This can be done by using different macros to close
135 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
136 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
137 releases the Tcl lock.
138
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000139 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000140 handlers when the handler needs to use Python. Such event handlers are
141 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000142 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000143 the Python interpreter lock, restoring the appropriate thread state, and
144 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
145 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000146 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000147
148 These locks expand to several statements and brackets; they should not be
149 used in branches of if statements and the like.
150
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000151 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
152 only valid in the thread that created it, and all Tk activity must happen in this
153 thread, also. That means that the mainloop must be invoked in the thread that
154 created the interpreter. Invoking commands from other threads is possible;
155 _tkinter will queue an event for the interpreter thread, which will then
156 execute the command and pass back the result. If the main thread is not in the
157 mainloop, and invoking commands causes an exception; if the main loop is running
158 but not processing events, the command invocation will block.
159
160 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
161 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
162 threads. So we use the Tcl TLS API.
163
Guido van Rossum00d93061998-05-28 23:06:38 +0000164*/
165
Guido van Rossum65d5b571998-12-21 19:32:43 +0000166static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000167
168#ifdef TCL_THREADS
169static Tcl_ThreadDataKey state_key;
170typedef PyThreadState *ThreadSpecificData;
171#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
172#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000173static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000174#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000175
176#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000177 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000178 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000179
180#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000181 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000182
Guido van Rossum62320c91998-06-15 04:36:09 +0000183#define ENTER_OVERLAP \
184 Py_END_ALLOW_THREADS
185
186#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000187 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000188
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000189#define ENTER_PYTHON \
190 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000191 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000192
193#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000194 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000195 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
196
197#define CHECK_TCL_APPARTMENT \
198 if (((TkappObject *)self)->threaded && \
199 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
200 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
201 return 0; \
202 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000203
204#else
205
206#define ENTER_TCL
207#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000208#define ENTER_OVERLAP
209#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000210#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000211#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000212#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000213
214#endif
215
Guido van Rossumec22c921996-02-25 04:50:29 +0000216#ifdef macintosh
217
218/*
219** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000220** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000221*/
222
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000223/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000224#define FREECAST (char *)
225
Guido van Rossumec22c921996-02-25 04:50:29 +0000226#include <Events.h> /* For EventRecord */
227
Fred Drake509d79a2000-07-08 04:04:38 +0000228typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
Guido van Rossum2834b972000-10-06 16:58:26 +0000229void Tcl_MacSetEventProc(TclMacConvertEventPtr procPtr);
230int TkMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000231
Jeremy Hylton938ace62002-07-17 16:30:39 +0000232static int PyMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000233
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000234#include <SIOUX.h>
235extern int SIOUXIsAppWindow(WindowPtr);
236
Guido van Rossumec22c921996-02-25 04:50:29 +0000237#endif /* macintosh */
238
Guido van Rossum97867b21996-08-08 19:09:53 +0000239#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000240#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000241#endif
242
Guido van Rossum18468821994-06-20 07:49:28 +0000243/**** Tkapp Object Declaration ****/
244
Jeremy Hylton938ace62002-07-17 16:30:39 +0000245static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000246
Guido van Rossum00d93061998-05-28 23:06:38 +0000247typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000248 PyObject_HEAD
249 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000250 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000251 int threaded; /* True if tcl_platform[threaded] */
252 Tcl_ThreadId thread_id;
253 int dispatching;
254 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000255 So we cache interesting types here. */
256 Tcl_ObjType *BooleanType;
257 Tcl_ObjType *ByteArrayType;
258 Tcl_ObjType *DoubleType;
259 Tcl_ObjType *IntType;
260 Tcl_ObjType *ListType;
261 Tcl_ObjType *ProcBodyType;
262 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000263} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000264
265#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000266#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000267#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000268
Guido van Rossum35d43371997-08-02 00:09:09 +0000269#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000270(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000271
Barry Warsawfa701a81997-01-16 00:15:11 +0000272
273
Guido van Rossum18468821994-06-20 07:49:28 +0000274/**** Error Handling ****/
275
276static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000277static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000278static int errorInCmd = 0;
279static PyObject *excInCmd;
280static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000281static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
284
Guido van Rossum18468821994-06-20 07:49:28 +0000285static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000286Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000287{
Barry Warsawfa701a81997-01-16 00:15:11 +0000288 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
289 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000290}
291
Barry Warsawfa701a81997-01-16 00:15:11 +0000292
Barry Warsawfa701a81997-01-16 00:15:11 +0000293
Guido van Rossum18468821994-06-20 07:49:28 +0000294/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000295
296#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000297#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000298
Guido van Rossum00d93061998-05-28 23:06:38 +0000299/* Millisecond sleep() for Unix platforms. */
300
301static void
Fred Drake509d79a2000-07-08 04:04:38 +0000302Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000303{
304 /* XXX Too bad if you don't have select(). */
305 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000306 t.tv_sec = milli/1000;
307 t.tv_usec = (milli%1000) * 1000;
308 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
309}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000310#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000311#endif /* WITH_THREAD */
312
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000313/* Wait up to 1s for the mainloop to come up. */
314
315static int
316WaitForMainloop(TkappObject* self)
317{
318 int i;
319 for (i = 0; i < 10; i++) {
320 if (self->dispatching)
321 return 1;
322 Py_BEGIN_ALLOW_THREADS
323 Sleep(100);
324 Py_END_ALLOW_THREADS
325 }
326 if (self->dispatching)
327 return 1;
328 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
329 return 0;
330}
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000331
Guido van Rossum00d93061998-05-28 23:06:38 +0000332
Guido van Rossum18468821994-06-20 07:49:28 +0000333static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000334AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000335{
Guido van Rossum35d43371997-08-02 00:09:09 +0000336 if (PyString_Check(value))
337 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000338#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000339 else if (PyUnicode_Check(value)) {
340 PyObject *v = PyUnicode_AsUTF8String(value);
341 if (v == NULL)
342 return NULL;
343 if (PyList_Append(tmp, v) != 0) {
344 Py_DECREF(v);
345 return NULL;
346 }
347 Py_DECREF(v);
348 return PyString_AsString(v);
349 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000350#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000351 else {
352 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000353 if (v == NULL)
354 return NULL;
355 if (PyList_Append(tmp, v) != 0) {
356 Py_DECREF(v);
357 return NULL;
358 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000359 Py_DECREF(v);
360 return PyString_AsString(v);
361 }
Guido van Rossum18468821994-06-20 07:49:28 +0000362}
363
Barry Warsawfa701a81997-01-16 00:15:11 +0000364
365
Guido van Rossum18468821994-06-20 07:49:28 +0000366#define ARGSZ 64
367
368static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000369Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000370{
Barry Warsawfa701a81997-01-16 00:15:11 +0000371 PyObject *tmp = NULL;
372 char *argvStore[ARGSZ];
373 char **argv = NULL;
374 int fvStore[ARGSZ];
375 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000376 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000377 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000378
Barry Warsawfa701a81997-01-16 00:15:11 +0000379 if (!(tmp = PyList_New(0)))
380 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000381
Barry Warsawfa701a81997-01-16 00:15:11 +0000382 argv = argvStore;
383 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000384
Barry Warsawfa701a81997-01-16 00:15:11 +0000385 if (args == NULL)
386 argc = 0;
387
388 else if (!PyTuple_Check(args)) {
389 argc = 1;
390 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000391 if (!(argv[0] = AsString(args, tmp)))
392 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000393 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000394 else {
395 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000396
Barry Warsawfa701a81997-01-16 00:15:11 +0000397 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000398 argv = (char **)ckalloc(argc * sizeof(char *));
399 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000400 if (argv == NULL || fv == NULL) {
401 PyErr_NoMemory();
402 goto finally;
403 }
404 }
405
406 for (i = 0; i < argc; i++) {
407 PyObject *v = PyTuple_GetItem(args, i);
408 if (PyTuple_Check(v)) {
409 fv[i] = 1;
410 if (!(argv[i] = Merge(v)))
411 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000412 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000413 }
414 else if (v == Py_None) {
415 argc = i;
416 break;
417 }
418 else {
419 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000420 if (!(argv[i] = AsString(v, tmp)))
421 goto finally;
422 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000423 }
424 }
Guido van Rossum18468821994-06-20 07:49:28 +0000425 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000426 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000427 if (res == NULL)
428 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000429
Barry Warsawfa701a81997-01-16 00:15:11 +0000430 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000431 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000432 if (fv[i]) {
433 ckfree(argv[i]);
434 }
435 if (argv != argvStore)
436 ckfree(FREECAST argv);
437 if (fv != fvStore)
438 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000439
Barry Warsawfa701a81997-01-16 00:15:11 +0000440 Py_DECREF(tmp);
441 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000442}
443
Barry Warsawfa701a81997-01-16 00:15:11 +0000444
445
Guido van Rossum18468821994-06-20 07:49:28 +0000446static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000447Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000448{
Barry Warsawfa701a81997-01-16 00:15:11 +0000449 int argc;
450 char **argv;
451 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000452
Barry Warsawfa701a81997-01-16 00:15:11 +0000453 if (list == NULL) {
454 Py_INCREF(Py_None);
455 return Py_None;
456 }
Guido van Rossum18468821994-06-20 07:49:28 +0000457
Guido van Rossum00d93061998-05-28 23:06:38 +0000458 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000459 /* Not a list.
460 * Could be a quoted string containing funnies, e.g. {"}.
461 * Return the string itself.
462 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000463 return PyString_FromString(list);
464 }
Guido van Rossum18468821994-06-20 07:49:28 +0000465
Barry Warsawfa701a81997-01-16 00:15:11 +0000466 if (argc == 0)
467 v = PyString_FromString("");
468 else if (argc == 1)
469 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000470 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000471 int i;
472 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000473
Barry Warsawfa701a81997-01-16 00:15:11 +0000474 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000475 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000476 Py_DECREF(v);
477 v = NULL;
478 break;
479 }
480 PyTuple_SetItem(v, i, w);
481 }
482 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000483 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000484 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000485}
486
Martin v. Löwisffad6332002-11-26 09:28:05 +0000487/* In some cases, Tcl will still return strings that are supposed to be
488 lists. SplitObj walks through a nested tuple, finding string objects that
489 need to be split. */
490
491PyObject *
492SplitObj(PyObject *arg)
493{
494 if (PyTuple_Check(arg)) {
495 int i, size;
496 PyObject *elem, *newelem, *result;
497
498 size = PyTuple_Size(arg);
499 result = NULL;
500 /* Recursively invoke SplitObj for all tuple items.
501 If this does not return a new object, no action is
502 needed. */
503 for(i = 0; i < size; i++) {
504 elem = PyTuple_GetItem(arg, i);
505 newelem = SplitObj(elem);
506 if (!newelem) {
507 Py_XDECREF(result);
508 return NULL;
509 }
510 if (!result) {
511 int k;
512 if (newelem == elem) {
513 Py_DECREF(newelem);
514 continue;
515 }
516 result = PyTuple_New(size);
517 if (!result)
518 return NULL;
519 for(k = 0; k < i; k++) {
520 elem = PyTuple_GetItem(arg, k);
521 Py_INCREF(elem);
522 PyTuple_SetItem(result, k, elem);
523 }
524 }
525 PyTuple_SetItem(result, i, newelem);
526 }
527 if (result)
528 return result;
529 /* Fall through, returning arg. */
530 }
531 else if (PyString_Check(arg)) {
532 int argc;
533 char **argv;
534 char *list = PyString_AsString(arg);
535
536 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
537 Py_INCREF(arg);
538 return arg;
539 }
540 Tcl_Free(FREECAST argv);
541 if (argc > 1)
542 return Split(PyString_AsString(arg));
543 /* Fall through, returning arg. */
544 }
545 Py_INCREF(arg);
546 return arg;
547}
Barry Warsawfa701a81997-01-16 00:15:11 +0000548
549
Guido van Rossum18468821994-06-20 07:49:28 +0000550/**** Tkapp Object ****/
551
552#ifndef WITH_APPINIT
553int
Fred Drake509d79a2000-07-08 04:04:38 +0000554Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000555{
Barry Warsawfa701a81997-01-16 00:15:11 +0000556 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000557
Barry Warsawfa701a81997-01-16 00:15:11 +0000558 main = Tk_MainWindow(interp);
559 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000560 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000561 return TCL_ERROR;
562 }
563 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000564 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000565 return TCL_ERROR;
566 }
567 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000568}
569#endif /* !WITH_APPINIT */
570
Guido van Rossum18468821994-06-20 07:49:28 +0000571
Barry Warsawfa701a81997-01-16 00:15:11 +0000572
573
574/* Initialize the Tk application; see the `main' function in
575 * `tkMain.c'.
576 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000577
Thomas Wouters58d05102000-07-24 14:43:35 +0000578static void EnableEventHook(void); /* Forward */
579static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000580
Barry Warsawfa701a81997-01-16 00:15:11 +0000581static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000582Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000583 int interactive, int wantobjects)
Barry Warsawfa701a81997-01-16 00:15:11 +0000584{
585 TkappObject *v;
586 char *argv0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000587
Guido van Rossumb18618d2000-05-03 23:44:39 +0000588 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000589 if (v == NULL)
590 return NULL;
591
592 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000593 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000594 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
595 TCL_GLOBAL_ONLY) != NULL;
596 v->thread_id = Tcl_GetCurrentThread();
597 v->dispatching = 0;
598
599#ifndef TCL_THREADS
600 if (v->threaded) {
601 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
602 Py_DECREF(v);
603 return 0;
604 }
605#endif
606 if (v->threaded && tcl_lock) {
607 /* If Tcl is threaded, we don't need the lock. */
608 PyThread_free_lock(tcl_lock);
609 tcl_lock = NULL;
610 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000611
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000612 v->BooleanType = Tcl_GetObjType("boolean");
613 v->ByteArrayType = Tcl_GetObjType("bytearray");
614 v->DoubleType = Tcl_GetObjType("double");
615 v->IntType = Tcl_GetObjType("int");
616 v->ListType = Tcl_GetObjType("list");
617 v->ProcBodyType = Tcl_GetObjType("procbody");
618 v->StringType = Tcl_GetObjType("string");
619
Guido van Rossuma80649b2000-03-28 20:07:05 +0000620#if defined(macintosh)
621 /* This seems to be needed */
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000622 ClearMenuBar();
623 TkMacInitMenus(v->interp);
624#endif
Jack Jansencb852442001-12-09 23:15:56 +0000625
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000626 /* Delete the 'exit' command, which can screw things up */
627 Tcl_DeleteCommand(v->interp, "exit");
628
Barry Warsawfa701a81997-01-16 00:15:11 +0000629 if (screenName != NULL)
630 Tcl_SetVar2(v->interp, "env", "DISPLAY",
631 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000632
Barry Warsawfa701a81997-01-16 00:15:11 +0000633 if (interactive)
634 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
635 else
636 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000637
Barry Warsawfa701a81997-01-16 00:15:11 +0000638 /* This is used to get the application class for Tk 4.1 and up */
639 argv0 = (char*)ckalloc(strlen(className) + 1);
640 if (!argv0) {
641 PyErr_NoMemory();
642 Py_DECREF(v);
643 return NULL;
644 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000645
Barry Warsawfa701a81997-01-16 00:15:11 +0000646 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000647 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000648 argv0[0] = tolower(argv0[0]);
649 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
650 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000651
Barry Warsawfa701a81997-01-16 00:15:11 +0000652 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000653 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000654
Guido van Rossum7bf15641998-05-22 18:28:17 +0000655 EnableEventHook();
656
Barry Warsawfa701a81997-01-16 00:15:11 +0000657 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000658}
659
Barry Warsawfa701a81997-01-16 00:15:11 +0000660
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000661static void
662Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
663 Tcl_Condition *cond, Tcl_Mutex *mutex)
664{
665 Py_BEGIN_ALLOW_THREADS;
666 Tcl_MutexLock(mutex);
667 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
668 Tcl_ThreadAlert(self->thread_id);
669 Tcl_ConditionWait(cond, mutex, NULL);
670 Tcl_MutexUnlock(mutex);
671 Py_END_ALLOW_THREADS
672}
673
Barry Warsawfa701a81997-01-16 00:15:11 +0000674
Guido van Rossum18468821994-06-20 07:49:28 +0000675/** Tcl Eval **/
676
Martin v. Löwisffad6332002-11-26 09:28:05 +0000677typedef struct {
678 PyObject_HEAD
679 Tcl_Obj *value;
680} PyTclObject;
681
682staticforward PyTypeObject PyTclObject_Type;
683#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
684
685static PyObject *
686newPyTclObject(Tcl_Obj *arg)
687{
688 PyTclObject *self;
689 self = PyObject_New(PyTclObject, &PyTclObject_Type);
690 if (self == NULL)
691 return NULL;
692 Tcl_IncrRefCount(arg);
693 self->value = arg;
694 return (PyObject*)self;
695}
696
697static void
698PyTclObject_dealloc(PyTclObject *self)
699{
700 Tcl_DecrRefCount(self->value);
701 PyObject_Del(self);
702}
703
704static PyObject *
705PyTclObject_str(PyTclObject *self)
706{
707 return PyString_FromString(Tcl_GetString(self->value));
708}
709
710static PyObject *
711PyTclObject_repr(PyTclObject *self)
712{
713 char buf[50];
714 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
715 self->value->typePtr->name, (int)self->value);
716 return PyString_FromString(buf);
717}
718
719static PyObject*
720get_typename(PyTclObject* obj, void* ignored)
721{
722 return PyString_FromString(obj->value->typePtr->name);
723}
724
725static PyGetSetDef PyTclObject_getsetlist[] = {
726 {"typename", (getter)get_typename, NULL, "name of the Tcl type"},
727 {0},
728};
729
730statichere PyTypeObject PyTclObject_Type = {
731 PyObject_HEAD_INIT(NULL)
732 0, /*ob_size*/
733 "_tkinter.Tcl_Obj", /*tp_name*/
734 sizeof(PyTclObject), /*tp_basicsize*/
735 0, /*tp_itemsize*/
736 /* methods */
737 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
738 0, /*tp_print*/
739 0, /*tp_getattr*/
740 0, /*tp_setattr*/
741 0, /*tp_compare*/
742 (reprfunc)PyTclObject_repr, /*tp_repr*/
743 0, /*tp_as_number*/
744 0, /*tp_as_sequence*/
745 0, /*tp_as_mapping*/
746 0, /*tp_hash*/
747 0, /*tp_call*/
748 (reprfunc)PyTclObject_str, /*tp_str*/
749 PyObject_GenericGetAttr,/*tp_getattro*/
750 0, /*tp_setattro*/
751 0, /*tp_as_buffer*/
752 Py_TPFLAGS_DEFAULT, /*tp_flags*/
753 0, /*tp_doc*/
754 0, /*tp_traverse*/
755 0, /*tp_clear*/
756 0, /*tp_richcompare*/
757 0, /*tp_weaklistoffset*/
758 0, /*tp_iter*/
759 0, /*tp_iternext*/
760 0, /*tp_methods*/
761 0, /*tp_members*/
762 PyTclObject_getsetlist, /*tp_getset*/
763 0, /*tp_base*/
764 0, /*tp_dict*/
765 0, /*tp_descr_get*/
766 0, /*tp_descr_set*/
767 0, /*tp_dictoffset*/
768 0, /*tp_init*/
769 0, /*tp_alloc*/
770 0, /*tp_new*/
771 0, /*tp_free*/
772 0, /*tp_is_gc*/
773};
774
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000775static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000776AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000777{
778 Tcl_Obj *result;
779
780 if (PyString_Check(value))
781 return Tcl_NewStringObj(PyString_AS_STRING(value),
782 PyString_GET_SIZE(value));
783 else if (PyInt_Check(value))
784 return Tcl_NewLongObj(PyInt_AS_LONG(value));
785 else if (PyFloat_Check(value))
786 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
787 else if (PyTuple_Check(value)) {
788 Tcl_Obj **argv = (Tcl_Obj**)
789 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
790 int i;
791 if(!argv)
792 return 0;
793 for(i=0;i<PyTuple_Size(value);i++)
794 argv[i] = AsObj(PyTuple_GetItem(value,i));
795 result = Tcl_NewListObj(PyTuple_Size(value), argv);
796 ckfree(FREECAST argv);
797 return result;
798 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000799#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000800 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000801 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
802 int size = PyUnicode_GET_SIZE(value);
803 /* This #ifdef assumes that Tcl uses UCS-2.
804 See TCL_UTF_MAX test above. */
805#ifdef Py_UNICODE_WIDE
806 Tcl_UniChar *outbuf;
807 int i;
808 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
809 if (!outbuf) {
810 PyErr_NoMemory();
811 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000812 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000813 for (i = 0; i < size; i++) {
814 if (inbuf[i] >= 0x10000) {
815 /* Tcl doesn't do UTF-16, yet. */
816 PyErr_SetString(PyExc_ValueError,
817 "unsupported character");
818 ckfree(FREECAST outbuf);
819 return NULL;
820 }
821 outbuf[i] = inbuf[i];
822 }
823 result = Tcl_NewUnicodeObj(outbuf, size);
824 ckfree(FREECAST outbuf);
825 return result;
826#else
827 return Tcl_NewUnicodeObj(inbuf, size);
828#endif
829
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000830 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000831#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000832 else if(PyTclObject_Check(value)) {
833 Tcl_Obj *v = ((PyTclObject*)value)->value;
834 Tcl_IncrRefCount(v);
835 return v;
836 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000837 else {
838 PyObject *v = PyObject_Str(value);
839 if (!v)
840 return 0;
841 result = AsObj(v);
842 Py_DECREF(v);
843 return result;
844 }
845}
846
Martin v. Löwisffad6332002-11-26 09:28:05 +0000847static PyObject*
848FromObj(PyObject* tkapp, Tcl_Obj *value)
849{
850 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000851 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000852
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000853 if (value->typePtr == NULL) {
854 /* If the result contains any bytes with the top bit set,
855 it's UTF-8 and we should decode it to Unicode */
856#ifdef Py_USING_UNICODE
857 int i;
858 char *s = value->bytes;
859 int len = value->length;
860 for (i = 0; i < len; i++) {
861 if (value->bytes[i] & 0x80)
862 break;
863 }
864
865 if (i == value->length)
866 result = PyString_FromStringAndSize(s, len);
867 else {
868 /* Convert UTF-8 to Unicode string */
869 result = PyUnicode_DecodeUTF8(s, len, "strict");
870 if (result == NULL) {
871 PyErr_Clear();
872 result = PyString_FromStringAndSize(s, len);
873 }
874 }
875#else
876 res = PyString_FromStringAndSize(value->bytes, value->length);
877#endif
878 return result;
879 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000880
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000881 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000882 result = value->internalRep.longValue ? Py_True : Py_False;
883 Py_INCREF(result);
884 return result;
885 }
886
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000887 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000888 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000889 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000890 return PyString_FromStringAndSize(data, size);
891 }
892
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000893 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000894 return PyFloat_FromDouble(value->internalRep.doubleValue);
895 }
896
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000897 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000898 return PyInt_FromLong(value->internalRep.longValue);
899 }
900
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000901 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000902 int size;
903 int i, status;
904 PyObject *elem;
905 Tcl_Obj *tcl_elem;
906
907 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
908 if (status == TCL_ERROR)
909 return Tkinter_Error(tkapp);
910 result = PyTuple_New(size);
911 if (!result)
912 return NULL;
913 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000914 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +0000915 value, i, &tcl_elem);
916 if (status == TCL_ERROR) {
917 Py_DECREF(result);
918 return Tkinter_Error(tkapp);
919 }
920 elem = FromObj(tkapp, tcl_elem);
921 if (!elem) {
922 Py_DECREF(result);
923 return NULL;
924 }
925 PyTuple_SetItem(result, i, elem);
926 }
927 return result;
928 }
929
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000930 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000931 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000932 }
933
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000934 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000935#ifdef Py_USING_UNICODE
936#ifdef Py_UNICODE_WIDE
937 PyObject *result;
938 int size;
939 Tcl_UniChar *input;
940 Py_UNICODE *output;
941
942 size = Tcl_GetCharLength(value);
943 result = PyUnicode_FromUnicode(NULL, size);
944 if (!result)
945 return NULL;
946 input = Tcl_GetUnicode(value);
947 output = PyUnicode_AS_UNICODE(result);
948 while (size--)
949 *output++ = *input++;
950 return result;
951#else
952 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
953 Tcl_GetCharLength(value));
954#endif
955#else
956 int size;
957 char *c;
958 c = Tcl_GetStringFromObj(value, &size);
959 return PyString_FromStringAndSize(c, size);
960#endif
961 }
962
963 return newPyTclObject(value);
964}
965
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000966/* This mutex synchronizes inter-thread command calls. */
967
968TCL_DECLARE_MUTEX(call_mutex)
969
970typedef struct Tkapp_CallEvent {
971 Tcl_Event ev; /* Must be first */
972 TkappObject *self;
973 PyObject *args;
974 int flags;
975 PyObject **res;
976 PyObject **exc_type, **exc_value, **exc_tb;
977 Tcl_Condition done;
978} Tkapp_CallEvent;
979
980void
981Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +0000982{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000983 int i;
984 for (i = 0; i < objc; i++)
985 Tcl_DecrRefCount(objv[i]);
986 if (objv != objStore)
987 ckfree(FREECAST objv);
988}
Guido van Rossum18468821994-06-20 07:49:28 +0000989
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000990/* Convert Python objects to Tcl objects. This must happen in the
991 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +0000992
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000993static Tcl_Obj**
994Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
995{
996 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +0000997 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +0000998 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +0000999 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001000
Guido van Rossum212643f1998-04-29 16:22:14 +00001001 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001002 objv[0] = AsObj(args);
1003 if (objv[0] == 0)
1004 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001005 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001006 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001007 }
1008 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001009 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001010
Guido van Rossum632de272000-03-29 00:19:50 +00001011 if (objc > ARGSZ) {
1012 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1013 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001014 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001015 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001016 goto finally;
1017 }
1018 }
1019
Guido van Rossum632de272000-03-29 00:19:50 +00001020 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001021 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001022 if (v == Py_None) {
1023 objc = i;
1024 break;
1025 }
Guido van Rossum632de272000-03-29 00:19:50 +00001026 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001027 if (!objv[i]) {
1028 /* Reset objc, so it attempts to clear
1029 objects only up to i. */
1030 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001031 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001032 }
Guido van Rossum632de272000-03-29 00:19:50 +00001033 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001034 }
1035 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001036 *pobjc = objc;
1037 return objv;
1038finally:
1039 Tkapp_CallDeallocArgs(objv, objStore, objc);
1040 return NULL;
1041}
Guido van Rossum212643f1998-04-29 16:22:14 +00001042
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001043/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001044
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001045static PyObject*
1046Tkapp_CallResult(TkappObject *self)
1047{
1048 PyObject *res = NULL;
1049 if(self->wantobjects) {
1050 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001051 /* Not sure whether the IncrRef is necessary, but something
1052 may overwrite the interpreter result while we are
1053 converting it. */
1054 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001055 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001056 Tcl_DecrRefCount(value);
1057 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001058 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001059 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001060
Guido van Rossum990f5c62000-05-04 15:07:16 +00001061 /* If the result contains any bytes with the top bit set,
1062 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001063#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001064 while (*p != '\0') {
1065 if (*p & 0x80)
1066 break;
1067 p++;
1068 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001069
Guido van Rossum990f5c62000-05-04 15:07:16 +00001070 if (*p == '\0')
1071 res = PyString_FromStringAndSize(s, (int)(p-s));
1072 else {
1073 /* Convert UTF-8 to Unicode string */
1074 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001075 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1076 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001077 PyErr_Clear();
1078 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001079 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001080 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001081#else
1082 p = strchr(p, '\0');
1083 res = PyString_FromStringAndSize(s, (int)(p-s));
1084#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001085 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001086 return res;
1087}
Guido van Rossum632de272000-03-29 00:19:50 +00001088
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001089/* Tkapp_CallProc is the event procedure that is executed in the context of
1090 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1091 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001092
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001093static int
1094Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1095{
1096 Tcl_Obj *objStore[ARGSZ];
1097 Tcl_Obj **objv;
1098 int objc;
1099 int i;
1100 ENTER_PYTHON
1101 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1102 if (!objv) {
1103 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1104 *(e->res) = NULL;
1105 }
1106 LEAVE_PYTHON
1107 if (!objv)
1108 goto done;
1109 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1110 ENTER_PYTHON
1111 if (i == TCL_ERROR) {
1112 *(e->res) = NULL;
1113 *(e->exc_type) = NULL;
1114 *(e->exc_tb) = NULL;
1115 *(e->exc_value) = PyObject_CallFunction(
1116 Tkinter_TclError, "s",
1117 Tcl_GetStringResult(e->self->interp));
1118 }
1119 else {
1120 *(e->res) = Tkapp_CallResult(e->self);
1121 }
1122 LEAVE_PYTHON
1123 done:
1124 /* Wake up calling thread. */
1125 Tcl_MutexLock(&call_mutex);
1126 Tcl_ConditionNotify(&e->done);
1127 Tcl_MutexUnlock(&call_mutex);
1128 return 1;
1129}
1130
1131/* This is the main entry point for calling a Tcl command.
1132 It supports three cases, with regard to threading:
1133 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1134 the context of the calling thread.
1135 2. Tcl is threaded, caller of the command is in the interpreter thread:
1136 Execute the command in the calling thread. Since the Tcl lock will
1137 not be used, we can merge that with case 1.
1138 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1139 the interpreter thread. Allocation of Tcl objects needs to occur in the
1140 interpreter thread, so we ship the PyObject* args to the target thread,
1141 and perform processing there. */
1142
1143static PyObject *
1144Tkapp_Call(PyObject *_self, PyObject *args)
1145{
1146 Tcl_Obj *objStore[ARGSZ];
1147 Tcl_Obj **objv = NULL;
1148 int objc, i;
1149 PyObject *res = NULL;
1150 TkappObject *self = (TkappObject*)_self;
1151 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1152 int flags = TCL_EVAL_DIRECT;
1153
1154 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1155 /* We cannot call the command directly. Instead, we must
1156 marshal the parameters to the interpreter thread. */
1157 Tkapp_CallEvent *ev;
1158 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001159 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001160 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001161 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1162 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1163 ev->self = self;
1164 ev->args = args;
1165 ev->res = &res;
1166 ev->exc_type = &exc_type;
1167 ev->exc_value = &exc_value;
1168 ev->exc_tb = &exc_tb;
1169 ev->done = (Tcl_Condition)0;
1170
1171 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1172
1173 if (res == NULL) {
1174 if (exc_type)
1175 PyErr_Restore(exc_type, exc_value, exc_tb);
1176 else
1177 PyErr_SetObject(Tkinter_TclError, exc_value);
1178 }
1179 }
1180 else {
1181
1182 objv = Tkapp_CallArgs(args, objStore, &objc);
1183 if (!objv)
1184 return NULL;
1185
1186 ENTER_TCL
1187
1188 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1189
1190 ENTER_OVERLAP
1191
1192 if (i == TCL_ERROR)
1193 Tkinter_Error(_self);
1194 else
1195 res = Tkapp_CallResult(self);
1196
1197 LEAVE_OVERLAP_TCL
1198
1199 Tkapp_CallDeallocArgs(objv, objStore, objc);
1200 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001201 return res;
1202}
1203
1204
1205static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001206Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001207{
Guido van Rossum212643f1998-04-29 16:22:14 +00001208 /* Could do the same here as for Tkapp_Call(), but this is not used
1209 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1210 way for the user to do what all its Global* variants do (save and
1211 reset the scope pointer, call the local version, restore the saved
1212 scope pointer). */
1213
Guido van Rossum62320c91998-06-15 04:36:09 +00001214 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001215 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001216
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001217 CHECK_TCL_APPARTMENT;
1218
Guido van Rossum62320c91998-06-15 04:36:09 +00001219 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001220 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001221 int err;
1222 ENTER_TCL
1223 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001224 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001225 if (err == TCL_ERROR)
1226 res = Tkinter_Error(self);
1227 else
1228 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001229 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001230 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001231 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001232
1233 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001234}
1235
1236static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001237Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001238{
Barry Warsawfa701a81997-01-16 00:15:11 +00001239 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001240 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001241 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001242
Guido van Rossum43713e52000-02-29 13:59:29 +00001243 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001244 return NULL;
1245
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001246 CHECK_TCL_APPARTMENT;
1247
Guido van Rossum00d93061998-05-28 23:06:38 +00001248 ENTER_TCL
1249 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001250 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001251 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001252 res = Tkinter_Error(self);
1253 else
1254 res = PyString_FromString(Tkapp_Result(self));
1255 LEAVE_OVERLAP_TCL
1256 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001257}
1258
1259static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001260Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001261{
Barry Warsawfa701a81997-01-16 00:15:11 +00001262 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001263 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001264 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001265
Guido van Rossum43713e52000-02-29 13:59:29 +00001266 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001267 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001268
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001269 CHECK_TCL_APPARTMENT;
1270
Guido van Rossum00d93061998-05-28 23:06:38 +00001271 ENTER_TCL
1272 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001273 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001274 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001275 res = Tkinter_Error(self);
1276 else
1277 res = PyString_FromString(Tkapp_Result(self));
1278 LEAVE_OVERLAP_TCL
1279 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001280}
1281
1282static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001283Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001284{
Barry Warsawfa701a81997-01-16 00:15:11 +00001285 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001286 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001287 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001288
Guido van Rossum43713e52000-02-29 13:59:29 +00001289 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001290 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001291
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001292 CHECK_TCL_APPARTMENT;
1293
Guido van Rossum00d93061998-05-28 23:06:38 +00001294 ENTER_TCL
1295 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001296 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001297 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001298 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001299
Guido van Rossum62320c91998-06-15 04:36:09 +00001300 else
1301 res = PyString_FromString(Tkapp_Result(self));
1302 LEAVE_OVERLAP_TCL
1303 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001304}
1305
1306static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001307Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001308{
Barry Warsawfa701a81997-01-16 00:15:11 +00001309 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001310 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001311 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001312
Guido van Rossum35d43371997-08-02 00:09:09 +00001313 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001314 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001315
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001316 CHECK_TCL_APPARTMENT;
1317
Guido van Rossum00d93061998-05-28 23:06:38 +00001318 ENTER_TCL
1319 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001320 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001321 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001322 res = Tkinter_Error(self);
1323 else
1324 res = PyString_FromString(Tkapp_Result(self));
1325 LEAVE_OVERLAP_TCL
1326 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001327}
1328
1329static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001330Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001331{
Barry Warsawfa701a81997-01-16 00:15:11 +00001332 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001333
Guido van Rossum43713e52000-02-29 13:59:29 +00001334 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001335 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001336 CHECK_TCL_APPARTMENT;
1337
Guido van Rossum00d93061998-05-28 23:06:38 +00001338 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001339 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001340 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001341
Barry Warsawfa701a81997-01-16 00:15:11 +00001342 Py_INCREF(Py_None);
1343 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001344}
1345
Barry Warsawfa701a81997-01-16 00:15:11 +00001346
1347
Guido van Rossum18468821994-06-20 07:49:28 +00001348/** Tcl Variable **/
1349
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001350TCL_DECLARE_MUTEX(var_mutex)
1351
1352typedef const char* (*EventFunc1)(Tcl_Interp*, const char*, int);
1353typedef const char* (*EventFunc2)(Tcl_Interp*, const char*, const char*, int);
1354typedef const char* (*EventFunc3)(Tcl_Interp*, const char*, const char*, const char*, int);
1355typedef struct VarEvent {
1356 Tcl_Event ev; /* must be first */
1357 TkappObject *self;
1358 char* arg1;
1359 char* arg2;
1360 char* arg3;
1361 int flags;
1362 EventFunc1 func1;
1363 EventFunc2 func2;
1364 EventFunc3 func3;
1365 PyObject **res;
1366 PyObject **exc;
1367 Tcl_Condition cond;
1368 int coderesult;
1369} VarEvent;
1370
1371static const char*
1372var_perform(VarEvent *ev)
1373{
1374 if (!ev->arg2 && !ev->arg2)
1375 return ev->func1(ev->self->interp, ev->arg1, ev->flags);
1376 if (!ev->arg3)
1377 return ev->func2(ev->self->interp, ev->arg1,
1378 ev->arg2, ev->flags);
1379 return ev->func3(ev->self->interp, ev->arg1, ev->arg2,
1380 ev->arg3, ev->flags);
1381}
1382
1383static void
1384var_fill_result(VarEvent *ev, const char* res)
1385{
1386 if (ev->coderesult) {
1387 if ((int)res != TCL_ERROR) {
1388 Py_INCREF(Py_None);
1389 *(ev->res) = Py_None;
1390 return;
1391 }
1392 }
1393 else if (res) {
1394 *(ev->res) = PyString_FromString(res);
1395 return;
1396 }
1397
1398 *(ev->res) = NULL;
1399 *(ev->exc) = PyObject_CallFunction(
1400 Tkinter_TclError, "s",
1401 Tcl_GetStringResult(ev->self->interp));
1402
1403}
1404
1405static int
1406var_proc(VarEvent* ev, int flags)
1407{
1408 const char *result = var_perform(ev);
1409 ENTER_PYTHON
1410 var_fill_result(ev, result);
1411 Tcl_MutexLock(&var_mutex);
1412 Tcl_ConditionNotify(&ev->cond);
1413 Tcl_MutexUnlock(&var_mutex);
1414 LEAVE_PYTHON
1415 return 1;
1416}
1417
1418static PyObject*
1419var_invoke(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
1420 EventFunc1 func1, EventFunc2 func2, EventFunc3 func3,
1421 int coderesult)
1422{
1423 VarEvent _ev;
1424 TkappObject *self = (TkappObject*)_self;
1425 VarEvent *ev = self->threaded ?
1426 (VarEvent*)ckalloc(sizeof(VarEvent)) : &_ev;
1427 PyObject *res, *exc;
1428
1429 ev->self = self;
1430 ev->arg1 = arg1;
1431 ev->arg2 = arg2;
1432 ev->arg3 = arg3;
1433 ev->flags = flags;
1434 ev->func1 = func1;
1435 ev->func2 = func2;
1436 ev->func3 = func3;
1437 ev->coderesult = coderesult;
1438 ev->res = &res;
1439 ev->exc = &exc;
1440 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1441 /* The current thread is not the interpreter thread. Marshal
1442 the call to the interpreter thread, then wait for
1443 completion. */
1444
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001445 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001446 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001447 ev->cond = NULL;
1448 ev->ev.proc = (Tcl_EventProc*)var_proc;
1449 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1450 }
1451 else {
1452 /* Tcl is not threaded, or this is the interpreter thread. To
1453 perform the call, we must hold the TCL lock. To receive the
1454 results, we must also hold the Python lock. */
1455 const char *result;
1456 ENTER_TCL
1457 result = var_perform(ev);
1458 ENTER_OVERLAP
1459 var_fill_result(ev, result);
1460 LEAVE_OVERLAP_TCL
1461 }
1462 if (!res) {
1463 PyErr_SetObject(Tkinter_TclError, exc);
1464 return NULL;
1465 }
1466 return res;
1467}
1468
1469static PyObject*
1470var_invoke2(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
1471 int (*func1)(Tcl_Interp*, const char*, int),
1472 int (*func2)(Tcl_Interp*, const char*, const char*, int),
1473 int (*func3)(Tcl_Interp*, const char*, const char*, const char*, int))
1474{
1475 return var_invoke(_self, arg1, arg2, arg3, flags,
1476 (EventFunc1)func1, (EventFunc2)func2,
1477 (EventFunc3)func3, 1);
1478}
1479
Guido van Rossum18468821994-06-20 07:49:28 +00001480static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001481SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001482{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001483 char *name1, *name2, *s;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001484 PyObject *res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001485 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +00001486 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +00001487
Guido van Rossum62320c91998-06-15 04:36:09 +00001488 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +00001489 if (!tmp)
1490 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001491
Guido van Rossum43713e52000-02-29 13:59:29 +00001492 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001493 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +00001494 s = AsString(newValue, tmp);
Guido van Rossum2834b972000-10-06 16:58:26 +00001495 if (s == NULL)
1496 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001497 res = var_invoke(self, name1, s, NULL, flags,
1498 NULL, Tcl_SetVar, NULL, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001499 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001500 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001501 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001502 if (PyArg_ParseTuple(args, "ssO:setvar",
1503 &name1, &name2, &newValue)) {
1504 s = AsString(newValue, tmp);
1505 if (s == NULL)
1506 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001507 res = var_invoke(self, name1, name2, s, flags,
1508 NULL, NULL, Tcl_SetVar2, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001509 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001510 else {
Guido van Rossum00d93061998-05-28 23:06:38 +00001511 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +00001512 return NULL;
1513 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001514 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001515 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +00001516
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001517 if (!res)
1518 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001519
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001520 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001521 Py_INCREF(Py_None);
1522 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001523}
1524
1525static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001526Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001527{
Barry Warsawfa701a81997-01-16 00:15:11 +00001528 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001529}
1530
1531static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001532Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001533{
Barry Warsawfa701a81997-01-16 00:15:11 +00001534 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001535}
1536
Barry Warsawfa701a81997-01-16 00:15:11 +00001537
1538
Guido van Rossum18468821994-06-20 07:49:28 +00001539static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001540GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001541{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001542 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001543 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001544
Guido van Rossum43713e52000-02-29 13:59:29 +00001545 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001546 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001547
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001548 res = var_invoke(self, name1, name2, NULL, flags,
1549 Tcl_GetVar, Tcl_GetVar2, NULL, 0);
Guido van Rossum62320c91998-06-15 04:36:09 +00001550 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001551}
1552
1553static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001554Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001555{
Barry Warsawfa701a81997-01-16 00:15:11 +00001556 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001557}
1558
1559static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001560Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001561{
Barry Warsawfa701a81997-01-16 00:15:11 +00001562 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001563}
1564
Barry Warsawfa701a81997-01-16 00:15:11 +00001565
1566
Guido van Rossum18468821994-06-20 07:49:28 +00001567static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001568UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001569{
Guido van Rossum35d43371997-08-02 00:09:09 +00001570 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001571 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001572
Guido van Rossum43713e52000-02-29 13:59:29 +00001573 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001574 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001575
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001576 res = var_invoke2(self, name1, name2, NULL, flags,
1577 Tcl_UnsetVar, Tcl_UnsetVar2, NULL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001578 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001579}
1580
1581static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001582Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001583{
Barry Warsawfa701a81997-01-16 00:15:11 +00001584 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001585}
1586
1587static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001588Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001589{
Barry Warsawfa701a81997-01-16 00:15:11 +00001590 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001591}
1592
Barry Warsawfa701a81997-01-16 00:15:11 +00001593
1594
Guido van Rossum18468821994-06-20 07:49:28 +00001595/** Tcl to Python **/
1596
1597static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001598Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001599{
Barry Warsawfa701a81997-01-16 00:15:11 +00001600 char *s;
1601 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001602
Martin v. Löwisffad6332002-11-26 09:28:05 +00001603 if (PyTuple_Size(args) == 1) {
1604 PyObject* o = PyTuple_GetItem(args, 0);
1605 if (PyInt_Check(o)) {
1606 Py_INCREF(o);
1607 return o;
1608 }
1609 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001610 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001611 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001612 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001613 return Tkinter_Error(self);
1614 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001615}
1616
1617static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001618Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001619{
Barry Warsawfa701a81997-01-16 00:15:11 +00001620 char *s;
1621 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001622
Martin v. Löwisffad6332002-11-26 09:28:05 +00001623 if (PyTuple_Size(args) == 1) {
1624 PyObject *o = PyTuple_GetItem(args, 0);
1625 if (PyFloat_Check(o)) {
1626 Py_INCREF(o);
1627 return o;
1628 }
1629 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001630 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001631 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001632 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001633 return Tkinter_Error(self);
1634 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001635}
1636
1637static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001638Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001639{
Barry Warsawfa701a81997-01-16 00:15:11 +00001640 char *s;
1641 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001642
Martin v. Löwisffad6332002-11-26 09:28:05 +00001643 if (PyTuple_Size(args) == 1) {
1644 PyObject *o = PyTuple_GetItem(args, 0);
1645 if (PyInt_Check(o)) {
1646 Py_INCREF(o);
1647 return o;
1648 }
1649 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001650 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001651 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001652 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1653 return Tkinter_Error(self);
Barry Warsawfa701a81997-01-16 00:15:11 +00001654 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001655}
1656
1657static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001658Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001659{
Barry Warsawfa701a81997-01-16 00:15:11 +00001660 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001661 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001662 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001663
Guido van Rossum43713e52000-02-29 13:59:29 +00001664 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001665 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001666
1667 CHECK_TCL_APPARTMENT;
1668
Guido van Rossum00d93061998-05-28 23:06:38 +00001669 ENTER_TCL
1670 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001671 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001672 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001673 res = Tkinter_Error(self);
1674 else
1675 res = Py_BuildValue("s", Tkapp_Result(self));
1676 LEAVE_OVERLAP_TCL
1677 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001678}
1679
1680static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001681Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001682{
Barry Warsawfa701a81997-01-16 00:15:11 +00001683 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001684 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001685 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001686 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001687
Guido van Rossum43713e52000-02-29 13:59:29 +00001688 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001689 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001690
1691 CHECK_TCL_APPARTMENT;
1692
Guido van Rossum00d93061998-05-28 23:06:38 +00001693 ENTER_TCL
1694 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001695 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001696 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001697 res = Tkinter_Error(self);
1698 else
1699 res = Py_BuildValue("l", v);
1700 LEAVE_OVERLAP_TCL
1701 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001702}
1703
1704static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001705Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001706{
Barry Warsawfa701a81997-01-16 00:15:11 +00001707 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001708 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001709 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001710 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001711
Guido van Rossum43713e52000-02-29 13:59:29 +00001712 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001713 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001714 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001715 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001716 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001717 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001718 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001719 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001720 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001721 res = Tkinter_Error(self);
1722 else
1723 res = Py_BuildValue("d", v);
1724 LEAVE_OVERLAP_TCL
1725 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001726}
1727
1728static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001729Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001730{
Barry Warsawfa701a81997-01-16 00:15:11 +00001731 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001732 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001733 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001734 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001735
Guido van Rossum43713e52000-02-29 13:59:29 +00001736 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001737 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001738 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001739 ENTER_TCL
1740 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001741 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001742 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001743 res = Tkinter_Error(self);
1744 else
1745 res = Py_BuildValue("i", v);
1746 LEAVE_OVERLAP_TCL
1747 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001748}
1749
Barry Warsawfa701a81997-01-16 00:15:11 +00001750
1751
Guido van Rossum18468821994-06-20 07:49:28 +00001752static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001753Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001754{
Barry Warsawfa701a81997-01-16 00:15:11 +00001755 char *list;
1756 int argc;
1757 char **argv;
1758 PyObject *v;
1759 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001760
Martin v. Löwisffad6332002-11-26 09:28:05 +00001761 if (PyTuple_Size(args) == 1) {
1762 v = PyTuple_GetItem(args, 0);
1763 if (PyTuple_Check(v)) {
1764 Py_INCREF(v);
1765 return v;
1766 }
1767 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001768 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001769 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001770
Barry Warsawfa701a81997-01-16 00:15:11 +00001771 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1772 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001773
Barry Warsawfa701a81997-01-16 00:15:11 +00001774 if (!(v = PyTuple_New(argc)))
1775 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001776
Barry Warsawfa701a81997-01-16 00:15:11 +00001777 for (i = 0; i < argc; i++) {
1778 PyObject *s = PyString_FromString(argv[i]);
1779 if (!s || PyTuple_SetItem(v, i, s)) {
1780 Py_DECREF(v);
1781 v = NULL;
1782 goto finally;
1783 }
1784 }
Guido van Rossum18468821994-06-20 07:49:28 +00001785
Barry Warsawfa701a81997-01-16 00:15:11 +00001786 finally:
1787 ckfree(FREECAST argv);
1788 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001789}
1790
1791static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001792Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001793{
Barry Warsawfa701a81997-01-16 00:15:11 +00001794 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001795
Martin v. Löwisffad6332002-11-26 09:28:05 +00001796 if (PyTuple_Size(args) == 1) {
1797 PyObject* o = PyTuple_GetItem(args, 0);
1798 if (PyTuple_Check(o)) {
1799 o = SplitObj(o);
1800 return o;
1801 }
1802 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001803 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001804 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001805 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001806}
1807
1808static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001809Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001810{
Barry Warsawfa701a81997-01-16 00:15:11 +00001811 char *s = Merge(args);
1812 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001813
Barry Warsawfa701a81997-01-16 00:15:11 +00001814 if (s) {
1815 res = PyString_FromString(s);
1816 ckfree(s);
1817 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001818
1819 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001820}
1821
Barry Warsawfa701a81997-01-16 00:15:11 +00001822
1823
Guido van Rossum18468821994-06-20 07:49:28 +00001824/** Tcl Command **/
1825
Guido van Rossum00d93061998-05-28 23:06:38 +00001826/* Client data struct */
1827typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001828 PyObject *self;
1829 PyObject *func;
1830} PythonCmd_ClientData;
1831
1832static int
Fred Drake509d79a2000-07-08 04:04:38 +00001833PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001834{
1835 errorInCmd = 1;
1836 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1837 LEAVE_PYTHON
1838 return TCL_ERROR;
1839}
1840
Guido van Rossum18468821994-06-20 07:49:28 +00001841/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001842 * function or method.
1843 */
Guido van Rossum18468821994-06-20 07:49:28 +00001844static int
Fred Drake509d79a2000-07-08 04:04:38 +00001845PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001846{
Guido van Rossum00d93061998-05-28 23:06:38 +00001847 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001848 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001849 int i, rv;
1850 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001851
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001852 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001853
Barry Warsawfa701a81997-01-16 00:15:11 +00001854 /* TBD: no error checking here since we know, via the
1855 * Tkapp_CreateCommand() that the client data is a two-tuple
1856 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001857 self = data->self;
1858 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001859
Barry Warsawfa701a81997-01-16 00:15:11 +00001860 /* Create argument list (argv1, ..., argvN) */
1861 if (!(arg = PyTuple_New(argc - 1)))
1862 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001863
Barry Warsawfa701a81997-01-16 00:15:11 +00001864 for (i = 0; i < (argc - 1); i++) {
1865 PyObject *s = PyString_FromString(argv[i + 1]);
1866 if (!s || PyTuple_SetItem(arg, i, s)) {
1867 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001868 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001869 }
1870 }
1871 res = PyEval_CallObject(func, arg);
1872 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001873
Barry Warsawfa701a81997-01-16 00:15:11 +00001874 if (res == NULL)
1875 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001876
Barry Warsawfa701a81997-01-16 00:15:11 +00001877 if (!(tmp = PyList_New(0))) {
1878 Py_DECREF(res);
1879 return PythonCmd_Error(interp);
1880 }
1881
Guido van Rossum2834b972000-10-06 16:58:26 +00001882 s = AsString(res, tmp);
1883 if (s == NULL) {
1884 rv = PythonCmd_Error(interp);
1885 }
1886 else {
1887 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1888 rv = TCL_OK;
1889 }
1890
Barry Warsawfa701a81997-01-16 00:15:11 +00001891 Py_DECREF(res);
1892 Py_DECREF(tmp);
1893
Guido van Rossum00d93061998-05-28 23:06:38 +00001894 LEAVE_PYTHON
1895
Guido van Rossum2834b972000-10-06 16:58:26 +00001896 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001897}
1898
1899static void
Fred Drake509d79a2000-07-08 04:04:38 +00001900PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001901{
Guido van Rossum00d93061998-05-28 23:06:38 +00001902 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1903
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001904 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001905 Py_XDECREF(data->self);
1906 Py_XDECREF(data->func);
1907 PyMem_DEL(data);
1908 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001909}
1910
Barry Warsawfa701a81997-01-16 00:15:11 +00001911
1912
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001913
1914TCL_DECLARE_MUTEX(command_mutex)
1915
1916typedef struct CommandEvent{
1917 Tcl_Event ev;
1918 Tcl_Interp* interp;
1919 char *name;
1920 int create;
1921 int *status;
1922 ClientData *data;
1923 Tcl_Condition done;
1924} CommandEvent;
1925
1926static int
1927Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001928{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001929 if (ev->create)
1930 *ev->status = Tcl_CreateCommand(
1931 ev->interp, ev->name, PythonCmd,
1932 ev->data, PythonCmdDelete) == NULL;
1933 else
1934 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1935 Tcl_MutexLock(&command_mutex);
1936 Tcl_ConditionNotify(&ev->done);
1937 Tcl_MutexUnlock(&command_mutex);
1938 return 1;
1939}
1940
1941static PyObject *
1942Tkapp_CreateCommand(PyObject *_self, PyObject *args)
1943{
1944 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001945 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001946 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00001947 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001948 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001949
Guido van Rossum43713e52000-02-29 13:59:29 +00001950 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00001951 return NULL;
1952 if (!PyCallable_Check(func)) {
1953 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00001954 return NULL;
1955 }
Guido van Rossum18468821994-06-20 07:49:28 +00001956
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001957 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001958 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001959 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001960
Guido van Rossum00d93061998-05-28 23:06:38 +00001961 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00001962 if (!data)
1963 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001964 Py_XINCREF(self);
1965 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001966 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001967 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001968
1969 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1970 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
1971 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
1972 ev->interp = self->interp;
1973 ev->create = 1;
1974 ev->name = cmdName;
1975 ev->data = (ClientData)data;
1976 ev->status = &err;
1977 ev->done = NULL;
1978 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
1979 }
1980 else {
1981 ENTER_TCL
1982 err = Tcl_CreateCommand(
1983 Tkapp_Interp(self), cmdName, PythonCmd,
1984 (ClientData)data, PythonCmdDelete) == NULL;
1985 LEAVE_TCL
1986 }
1987 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001988 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00001989 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00001990 return NULL;
1991 }
Guido van Rossum18468821994-06-20 07:49:28 +00001992
Barry Warsawfa701a81997-01-16 00:15:11 +00001993 Py_INCREF(Py_None);
1994 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001995}
1996
Barry Warsawfa701a81997-01-16 00:15:11 +00001997
1998
Guido van Rossum18468821994-06-20 07:49:28 +00001999static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002000Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002001{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002002 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002003 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002004 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002005
Guido van Rossum43713e52000-02-29 13:59:29 +00002006 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002007 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002008 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2009 CommandEvent *ev;
2010 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2011 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2012 ev->interp = self->interp;
2013 ev->create = 0;
2014 ev->name = cmdName;
2015 ev->status = &err;
2016 ev->done = NULL;
2017 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2018 &command_mutex);
2019 }
2020 else {
2021 ENTER_TCL
2022 err = Tcl_DeleteCommand(self->interp, cmdName);
2023 LEAVE_TCL
2024 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002025 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002026 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2027 return NULL;
2028 }
2029 Py_INCREF(Py_None);
2030 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002031}
2032
Barry Warsawfa701a81997-01-16 00:15:11 +00002033
2034
Guido van Rossum00d93061998-05-28 23:06:38 +00002035#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002036/** File Handler **/
2037
Guido van Rossum00d93061998-05-28 23:06:38 +00002038typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002039 PyObject *func;
2040 PyObject *file;
2041 int id;
2042 struct _fhcdata *next;
2043} FileHandler_ClientData;
2044
2045static FileHandler_ClientData *HeadFHCD;
2046
2047static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002048NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002049{
2050 FileHandler_ClientData *p;
2051 p = PyMem_NEW(FileHandler_ClientData, 1);
2052 if (p != NULL) {
2053 Py_XINCREF(func);
2054 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002055 p->func = func;
2056 p->file = file;
2057 p->id = id;
2058 p->next = HeadFHCD;
2059 HeadFHCD = p;
2060 }
2061 return p;
2062}
2063
2064static void
Fred Drake509d79a2000-07-08 04:04:38 +00002065DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002066{
2067 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002068
2069 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002070 while ((p = *pp) != NULL) {
2071 if (p->id == id) {
2072 *pp = p->next;
2073 Py_XDECREF(p->func);
2074 Py_XDECREF(p->file);
2075 PyMem_DEL(p);
2076 }
2077 else
2078 pp = &p->next;
2079 }
2080}
2081
Guido van Rossuma597dde1995-01-10 20:56:29 +00002082static void
Fred Drake509d79a2000-07-08 04:04:38 +00002083FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002084{
Guido van Rossum00d93061998-05-28 23:06:38 +00002085 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002086 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002087
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002088 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002089 func = data->func;
2090 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002091
Barry Warsawfa701a81997-01-16 00:15:11 +00002092 arg = Py_BuildValue("(Oi)", file, (long) mask);
2093 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002094 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002095
2096 if (res == NULL) {
2097 errorInCmd = 1;
2098 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2099 }
2100 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002101 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002102}
2103
Guido van Rossum18468821994-06-20 07:49:28 +00002104static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002105Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2106 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002107{
Guido van Rossum00d93061998-05-28 23:06:38 +00002108 FileHandler_ClientData *data;
2109 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002110 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002111
Guido van Rossum2834b972000-10-06 16:58:26 +00002112 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2113 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002114 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002115 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002116 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002117 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002118 return NULL;
2119 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002120 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002121 return NULL;
2122 }
2123
Guido van Rossuma80649b2000-03-28 20:07:05 +00002124 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002125 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002126 return NULL;
2127
Barry Warsawfa701a81997-01-16 00:15:11 +00002128 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002129 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002130 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002131 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002132 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002133 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002134}
2135
2136static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002137Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002138{
Barry Warsawfa701a81997-01-16 00:15:11 +00002139 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002140 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002141
Guido van Rossum43713e52000-02-29 13:59:29 +00002142 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002143 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002144 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002145 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002146 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002147 return NULL;
2148
Guido van Rossuma80649b2000-03-28 20:07:05 +00002149 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002150
Barry Warsawfa701a81997-01-16 00:15:11 +00002151 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002152 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002153 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002154 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002155 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002156 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002157}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002158#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002159
Barry Warsawfa701a81997-01-16 00:15:11 +00002160
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002161/**** Tktt Object (timer token) ****/
2162
Jeremy Hylton938ace62002-07-17 16:30:39 +00002163static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002164
Guido van Rossum00d93061998-05-28 23:06:38 +00002165typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002166 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002167 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002168 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002169} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002170
2171static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002172Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002173{
Barry Warsawfa701a81997-01-16 00:15:11 +00002174 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002175 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002176
Guido van Rossum43713e52000-02-29 13:59:29 +00002177 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002178 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002179 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002180 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002181 v->token = NULL;
2182 }
2183 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002184 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002185 Py_DECREF(func);
2186 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002187 }
2188 Py_INCREF(Py_None);
2189 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002190}
2191
2192static PyMethodDef Tktt_methods[] =
2193{
Neal Norwitzb0493252002-03-31 14:44:22 +00002194 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002195 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002196};
2197
2198static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002199Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002200{
Barry Warsawfa701a81997-01-16 00:15:11 +00002201 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002202
Guido van Rossumb18618d2000-05-03 23:44:39 +00002203 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002204 if (v == NULL)
2205 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002206
Guido van Rossum00d93061998-05-28 23:06:38 +00002207 Py_INCREF(func);
2208 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002209 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002210
2211 /* Extra reference, deleted when called or when handler is deleted */
2212 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002213 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002214}
2215
2216static void
Fred Drake509d79a2000-07-08 04:04:38 +00002217Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002218{
Guido van Rossum00d93061998-05-28 23:06:38 +00002219 TkttObject *v = (TkttObject *)self;
2220 PyObject *func = v->func;
2221
2222 Py_XDECREF(func);
2223
Guido van Rossumb18618d2000-05-03 23:44:39 +00002224 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002225}
2226
Guido van Rossum597ac201998-05-12 14:36:19 +00002227static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002228Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002229{
Barry Warsawfa701a81997-01-16 00:15:11 +00002230 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002231 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002232
Tim Peters885d4572001-11-28 20:27:42 +00002233 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002234 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002235 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002236}
2237
2238static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002239Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002240{
Barry Warsawfa701a81997-01-16 00:15:11 +00002241 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002242}
2243
2244static PyTypeObject Tktt_Type =
2245{
Guido van Rossum35d43371997-08-02 00:09:09 +00002246 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002247 0, /*ob_size */
2248 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002249 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002250 0, /*tp_itemsize */
2251 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002252 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002253 Tktt_GetAttr, /*tp_getattr */
2254 0, /*tp_setattr */
2255 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002256 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002257 0, /*tp_as_number */
2258 0, /*tp_as_sequence */
2259 0, /*tp_as_mapping */
2260 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002261};
2262
Barry Warsawfa701a81997-01-16 00:15:11 +00002263
2264
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002265/** Timer Handler **/
2266
2267static void
Fred Drake509d79a2000-07-08 04:04:38 +00002268TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002269{
Guido van Rossum00d93061998-05-28 23:06:38 +00002270 TkttObject *v = (TkttObject *)clientData;
2271 PyObject *func = v->func;
2272 PyObject *res;
2273
2274 if (func == NULL)
2275 return;
2276
2277 v->func = NULL;
2278
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002279 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002280
2281 res = PyEval_CallObject(func, NULL);
2282 Py_DECREF(func);
2283 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002284
Barry Warsawfa701a81997-01-16 00:15:11 +00002285 if (res == NULL) {
2286 errorInCmd = 1;
2287 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2288 }
2289 else
2290 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002291
2292 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002293}
2294
2295static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002296Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002297{
Barry Warsawfa701a81997-01-16 00:15:11 +00002298 int milliseconds;
2299 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002300 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002301
Guido van Rossum2834b972000-10-06 16:58:26 +00002302 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2303 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002304 return NULL;
2305 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002306 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002307 return NULL;
2308 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002309 v = Tktt_New(func);
2310 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2311 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002312
Guido van Rossum00d93061998-05-28 23:06:38 +00002313 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002314}
2315
Barry Warsawfa701a81997-01-16 00:15:11 +00002316
Guido van Rossum18468821994-06-20 07:49:28 +00002317/** Event Loop **/
2318
Guido van Rossum18468821994-06-20 07:49:28 +00002319static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002320Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002321{
Barry Warsawfa701a81997-01-16 00:15:11 +00002322 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002323 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002324#ifdef WITH_THREAD
2325 PyThreadState *tstate = PyThreadState_Get();
2326#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002327
Guido van Rossum43713e52000-02-29 13:59:29 +00002328 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002329 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002330
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002331 CHECK_TCL_APPARTMENT;
2332
Barry Warsawfa701a81997-01-16 00:15:11 +00002333 quitMainLoop = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002334 self->dispatching = 1;
Barry Warsawfa701a81997-01-16 00:15:11 +00002335 while (Tk_GetNumMainWindows() > threshold &&
2336 !quitMainLoop &&
2337 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002338 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002339 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002340
2341#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002342 if (self->threaded) {
2343 /* Allow other Python threads to run. */
2344 ENTER_TCL
2345 result = Tcl_DoOneEvent(0);
2346 LEAVE_TCL
2347 }
2348 else {
2349 Py_BEGIN_ALLOW_THREADS
2350 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2351 tcl_tstate = tstate;
2352 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2353 tcl_tstate = NULL;
2354 if(tcl_lock)PyThread_release_lock(tcl_lock);
2355 if (result == 0)
2356 Sleep(20);
2357 Py_END_ALLOW_THREADS
2358 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002359#else
2360 result = Tcl_DoOneEvent(0);
2361#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002362
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002363 if (PyErr_CheckSignals() != 0) {
2364 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002365 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002366 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002367 if (result < 0)
2368 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002369 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002370 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002371 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002372
Barry Warsawfa701a81997-01-16 00:15:11 +00002373 if (errorInCmd) {
2374 errorInCmd = 0;
2375 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2376 excInCmd = valInCmd = trbInCmd = NULL;
2377 return NULL;
2378 }
2379 Py_INCREF(Py_None);
2380 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002381}
2382
2383static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002384Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002385{
Guido van Rossum35d43371997-08-02 00:09:09 +00002386 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002387 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002388
Guido van Rossum43713e52000-02-29 13:59:29 +00002389 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002390 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002391 CHECK_TCL_APPARTMENT;
Barry Warsawfa701a81997-01-16 00:15:11 +00002392
Guido van Rossum00d93061998-05-28 23:06:38 +00002393 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002394 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002395 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002396 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002397}
2398
2399static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002400Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002401{
2402
Guido van Rossum43713e52000-02-29 13:59:29 +00002403 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002404 return NULL;
2405
2406 quitMainLoop = 1;
2407 Py_INCREF(Py_None);
2408 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002409}
2410
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002411static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002412Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002413{
2414
Guido van Rossum43713e52000-02-29 13:59:29 +00002415 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002416 return NULL;
2417
2418 return PyInt_FromLong((long)Tkapp_Interp(self));
2419}
2420
Barry Warsawfa701a81997-01-16 00:15:11 +00002421
Martin v. Löwisffad6332002-11-26 09:28:05 +00002422static PyObject *
2423Tkapp_WantObjects(PyObject *self, PyObject *args)
2424{
2425
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002426 int wantobjects;
2427 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002428 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002429 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002430
2431 Py_INCREF(Py_None);
2432 return Py_None;
2433}
2434
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002435static PyObject *
2436Tkapp_WillDispatch(PyObject *self, PyObject *args)
2437{
2438
2439 ((TkappObject*)self)->dispatching = 1;
2440
2441 Py_INCREF(Py_None);
2442 return Py_None;
2443}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002444
Barry Warsawfa701a81997-01-16 00:15:11 +00002445
Guido van Rossum18468821994-06-20 07:49:28 +00002446/**** Tkapp Method List ****/
2447
2448static PyMethodDef Tkapp_methods[] =
2449{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002450 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002451 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002452 {"call", Tkapp_Call, METH_OLDARGS},
2453 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2454 {"eval", Tkapp_Eval, METH_VARARGS},
2455 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2456 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2457 {"record", Tkapp_Record, METH_VARARGS},
2458 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2459 {"setvar", Tkapp_SetVar, METH_VARARGS},
2460 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2461 {"getvar", Tkapp_GetVar, METH_VARARGS},
2462 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2463 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2464 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2465 {"getint", Tkapp_GetInt, METH_VARARGS},
2466 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2467 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2468 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2469 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2470 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2471 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2472 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2473 {"split", Tkapp_Split, METH_VARARGS},
2474 {"merge", Tkapp_Merge, METH_OLDARGS},
2475 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2476 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002477#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002478 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2479 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002480#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002481 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2482 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2483 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2484 {"quit", Tkapp_Quit, METH_VARARGS},
2485 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002486 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002487};
2488
Barry Warsawfa701a81997-01-16 00:15:11 +00002489
2490
Guido van Rossum18468821994-06-20 07:49:28 +00002491/**** Tkapp Type Methods ****/
2492
2493static void
Fred Drake509d79a2000-07-08 04:04:38 +00002494Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002495{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002496 //CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00002497 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002498 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002499 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002500 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002501 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002502}
2503
2504static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002505Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002506{
Guido van Rossum35d43371997-08-02 00:09:09 +00002507 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002508}
2509
2510static PyTypeObject Tkapp_Type =
2511{
Guido van Rossum35d43371997-08-02 00:09:09 +00002512 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002513 0, /*ob_size */
2514 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002515 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002516 0, /*tp_itemsize */
2517 Tkapp_Dealloc, /*tp_dealloc */
2518 0, /*tp_print */
2519 Tkapp_GetAttr, /*tp_getattr */
2520 0, /*tp_setattr */
2521 0, /*tp_compare */
2522 0, /*tp_repr */
2523 0, /*tp_as_number */
2524 0, /*tp_as_sequence */
2525 0, /*tp_as_mapping */
2526 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002527};
2528
Barry Warsawfa701a81997-01-16 00:15:11 +00002529
2530
Guido van Rossum18468821994-06-20 07:49:28 +00002531/**** Tkinter Module ****/
2532
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002533typedef struct {
2534 PyObject* tuple;
2535 int size; /* current size */
2536 int maxsize; /* allocated size */
2537} FlattenContext;
2538
2539static int
2540_bump(FlattenContext* context, int size)
2541{
Guido van Rossum2834b972000-10-06 16:58:26 +00002542 /* expand tuple to hold (at least) size new items.
2543 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002544
2545 int maxsize = context->maxsize * 2;
2546
2547 if (maxsize < context->size + size)
2548 maxsize = context->size + size;
2549
2550 context->maxsize = maxsize;
2551
Tim Peters4324aa32001-05-28 22:30:08 +00002552 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002553}
2554
2555static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002556_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002557{
2558 /* add tuple or list to argument tuple (recursively) */
2559
2560 int i, size;
2561
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002562 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002563 PyErr_SetString(PyExc_ValueError,
2564 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002565 return 0;
2566 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002567 size = PyList_GET_SIZE(item);
2568 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002569 if (context->size + size > context->maxsize &&
2570 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002571 return 0;
2572 /* copy items to output tuple */
2573 for (i = 0; i < size; i++) {
2574 PyObject *o = PyList_GET_ITEM(item, i);
2575 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002576 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002577 return 0;
2578 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002579 if (context->size + 1 > context->maxsize &&
2580 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002581 return 0;
2582 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002583 PyTuple_SET_ITEM(context->tuple,
2584 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002585 }
2586 }
2587 } else if (PyTuple_Check(item)) {
2588 /* same, for tuples */
2589 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002590 if (context->size + size > context->maxsize &&
2591 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002592 return 0;
2593 for (i = 0; i < size; i++) {
2594 PyObject *o = PyTuple_GET_ITEM(item, i);
2595 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002596 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002597 return 0;
2598 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002599 if (context->size + 1 > context->maxsize &&
2600 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002601 return 0;
2602 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002603 PyTuple_SET_ITEM(context->tuple,
2604 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002605 }
2606 }
2607 } else {
2608 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2609 return 0;
2610 }
2611 return 1;
2612}
2613
2614static PyObject *
2615Tkinter_Flatten(PyObject* self, PyObject* args)
2616{
2617 FlattenContext context;
2618 PyObject* item;
2619
2620 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2621 return NULL;
2622
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002623 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002624 if (context.maxsize <= 0)
2625 return PyTuple_New(0);
2626
2627 context.tuple = PyTuple_New(context.maxsize);
2628 if (!context.tuple)
2629 return NULL;
2630
2631 context.size = 0;
2632
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002633 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002634 return NULL;
2635
Tim Peters4324aa32001-05-28 22:30:08 +00002636 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002637 return NULL;
2638
2639 return context.tuple;
2640}
2641
Guido van Rossum18468821994-06-20 07:49:28 +00002642static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002643Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002644{
Barry Warsawfa701a81997-01-16 00:15:11 +00002645 char *screenName = NULL;
2646 char *baseName = NULL;
2647 char *className = NULL;
2648 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002649 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002650
Guido van Rossum35d43371997-08-02 00:09:09 +00002651 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002652 if (baseName != NULL)
2653 baseName++;
2654 else
2655 baseName = Py_GetProgramName();
2656 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002657
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002658 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002659 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002660 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002661 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002662
Barry Warsawfa701a81997-01-16 00:15:11 +00002663 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002664 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002665}
2666
2667static PyMethodDef moduleMethods[] =
2668{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002669 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2670 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002671#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002672 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2673 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002674#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002675 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2676 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2677 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2678 {"quit", Tkapp_Quit, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002679 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002680};
2681
Guido van Rossum7bf15641998-05-22 18:28:17 +00002682#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002683
2684static int stdin_ready = 0;
2685
Guido van Rossumad4db171998-06-13 13:56:28 +00002686#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002687static void
Fred Drake509d79a2000-07-08 04:04:38 +00002688MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002689{
2690 stdin_ready = 1;
2691}
Guido van Rossumad4db171998-06-13 13:56:28 +00002692#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002693
Guido van Rossum00d93061998-05-28 23:06:38 +00002694static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002695
Guido van Rossum18468821994-06-20 07:49:28 +00002696static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002697EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002698{
Guido van Rossumad4db171998-06-13 13:56:28 +00002699#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002700 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002701#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002702#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002703 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002704#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002705 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002706 errorInCmd = 0;
2707#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002708 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002709 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002710#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002711 while (!errorInCmd && !stdin_ready) {
2712 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002713#ifdef MS_WINDOWS
2714 if (_kbhit()) {
2715 stdin_ready = 1;
2716 break;
2717 }
2718#endif
2719#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002720 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002721 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002722 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002723
Guido van Rossum00d93061998-05-28 23:06:38 +00002724 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002725
2726 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002727 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002728 if (result == 0)
2729 Sleep(20);
2730 Py_END_ALLOW_THREADS
2731#else
2732 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002733#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002734
2735 if (result < 0)
2736 break;
2737 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002738#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002739 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002740#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002741 if (errorInCmd) {
2742 errorInCmd = 0;
2743 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2744 excInCmd = valInCmd = trbInCmd = NULL;
2745 PyErr_Print();
2746 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002747#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002748 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002749#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002750 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002751}
Guido van Rossum18468821994-06-20 07:49:28 +00002752
Guido van Rossum00d93061998-05-28 23:06:38 +00002753#endif
2754
Guido van Rossum7bf15641998-05-22 18:28:17 +00002755static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002756EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002757{
Guido van Rossum00d93061998-05-28 23:06:38 +00002758#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002759 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002760#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002761 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002762#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002763 PyOS_InputHook = EventHook;
2764 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002765#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002766}
2767
2768static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002769DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002770{
Guido van Rossum00d93061998-05-28 23:06:38 +00002771#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002772 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2773 PyOS_InputHook = NULL;
2774 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002775#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002776}
2777
Barry Warsawfa701a81997-01-16 00:15:11 +00002778
2779/* all errors will be checked in one fell swoop in init_tkinter() */
2780static void
Fred Drake509d79a2000-07-08 04:04:38 +00002781ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002782{
2783 PyObject *v = PyInt_FromLong(val);
2784 if (v) {
2785 PyDict_SetItemString(d, name, v);
2786 Py_DECREF(v);
2787 }
2788}
2789static void
Fred Drake509d79a2000-07-08 04:04:38 +00002790ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002791{
2792 PyObject *v = PyString_FromString(val);
2793 if (v) {
2794 PyDict_SetItemString(d, name, v);
2795 Py_DECREF(v);
2796 }
2797}
2798
2799
Mark Hammond62b1ab12002-07-23 06:31:15 +00002800PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002801init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002802{
Barry Warsawfa701a81997-01-16 00:15:11 +00002803 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002804
Barry Warsawfa701a81997-01-16 00:15:11 +00002805 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002806
2807#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002808 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002809#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002810
Barry Warsawfa701a81997-01-16 00:15:11 +00002811 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002812
Barry Warsawfa701a81997-01-16 00:15:11 +00002813 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00002814 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00002815 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002816
Guido van Rossum35d43371997-08-02 00:09:09 +00002817 ins_long(d, "READABLE", TCL_READABLE);
2818 ins_long(d, "WRITABLE", TCL_WRITABLE);
2819 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2820 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2821 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2822 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2823 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2824 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2825 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002826 ins_string(d, "TK_VERSION", TK_VERSION);
2827 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002828
Guido van Rossum83551bf1997-09-13 00:44:23 +00002829 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002830
2831 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002832 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2833
Martin v. Löwisffad6332002-11-26 09:28:05 +00002834 PyTclObject_Type.ob_type = &PyType_Type;
2835 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002836
2837#ifdef TK_AQUA
2838 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2839 * start waking up. Note that Tcl_FindExecutable will do this, this
2840 * code must be above it! The original warning from
2841 * tkMacOSXAppInit.c is copied below.
2842 *
2843 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2844 * Tcl interpreter for now. It probably should work to do this
2845 * in the other order, but for now it doesn't seem to.
2846 *
2847 */
2848 Tk_MacOSXSetupTkNotifier();
2849#endif
2850
2851
Guido van Rossume187b0e2000-03-27 21:46:29 +00002852 /* This helps the dynamic loader; in Unicode aware Tcl versions
2853 it also helps Tcl find its encodings. */
2854 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00002855
Barry Warsawfa701a81997-01-16 00:15:11 +00002856 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002857 return;
2858
Guido van Rossum43ff8681998-07-14 18:02:13 +00002859#if 0
2860 /* This was not a good idea; through <Destroy> bindings,
2861 Tcl_Finalize() may invoke Python code but at that point the
2862 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002863 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002864#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002865
Jack Jansen34cc5c31995-10-31 16:15:12 +00002866#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002867 /*
2868 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2869 ** Most of the initializations in that routine (toolbox init calls and
2870 ** such) have already been done for us, so we only need these.
2871 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002872 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002873
2874 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00002875#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00002876 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00002877#endif /* GENERATINGCFM */
2878#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00002879}
Guido van Rossum9722ad81995-09-22 23:49:28 +00002880
Guido van Rossumec22c921996-02-25 04:50:29 +00002881
Barry Warsawfa701a81997-01-16 00:15:11 +00002882
Guido van Rossum9722ad81995-09-22 23:49:28 +00002883#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002884
2885/*
Guido van Rossumec22c921996-02-25 04:50:29 +00002886** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002887*/
2888
Guido van Rossum9722ad81995-09-22 23:49:28 +00002889void
2890panic(char * format, ...)
2891{
Barry Warsawfa701a81997-01-16 00:15:11 +00002892 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002893
Barry Warsawfa701a81997-01-16 00:15:11 +00002894 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002895
Guido van Rossum227cf761998-08-05 13:53:32 +00002896 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002897 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002898
Barry Warsawfa701a81997-01-16 00:15:11 +00002899 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002900
Barry Warsawfa701a81997-01-16 00:15:11 +00002901 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00002902}
Jack Jansen40b546d1995-11-14 10:34:45 +00002903
Guido van Rossumec22c921996-02-25 04:50:29 +00002904/*
2905** Pass events to SIOUX before passing them to Tk.
2906*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002907
Guido van Rossumec22c921996-02-25 04:50:29 +00002908static int
Fred Drake509d79a2000-07-08 04:04:38 +00002909PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002910{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002911 WindowPtr frontwin;
2912 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00002913 ** Sioux eats too many events, so we don't pass it everything. We
2914 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002915 ** the Sioux window is frontmost. This means that Tk menus don't work
2916 ** in that case, but at least we can scroll the sioux window.
2917 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2918 ** part of the external interface of Sioux...
2919 */
2920 frontwin = FrontWindow();
2921 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
2922 if (SIOUXHandleOneEvent(eventPtr))
2923 return 0; /* Nothing happened to the Tcl event queue */
2924 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002925 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002926}
2927
Guido van Rossumec22c921996-02-25 04:50:29 +00002928#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002929
2930/*
2931** Additional Mac specific code for dealing with shared libraries.
2932*/
2933
2934#include <Resources.h>
2935#include <CodeFragments.h>
2936
2937static int loaded_from_shlib = 0;
2938static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002939
Jack Jansen34cc5c31995-10-31 16:15:12 +00002940/*
2941** If this module is dynamically loaded the following routine should
2942** be the init routine. It takes care of adding the shared library to
2943** the resource-file chain, so that the tk routines can find their
2944** resources.
2945*/
2946OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002947init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002948{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00002949 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00002950 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002951 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002952 library_fss = *data->fragLocator.u.onDisk.fileSpec;
2953 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002954 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002955 library_fss = *data->fragLocator.u.inSegs.fileSpec;
2956 loaded_from_shlib = 1;
2957 }
2958 return noErr;
2959}
2960
2961/*
2962** Insert the library resources into the search path. Put them after
2963** the resources from the application. Again, we ignore errors.
2964*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002965static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002966mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002967{
2968 if ( !loaded_from_shlib )
2969 return;
2970 (void)FSpOpenResFile(&library_fss, fsRdPerm);
2971}
2972
Guido van Rossumec22c921996-02-25 04:50:29 +00002973#endif /* GENERATINGCFM */
2974#endif /* macintosh */