blob: 492198e085b41891ecb208d01b9e337fba9b2b6f [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öwisb5bfb9f2002-12-12 17:07:58 +0000313
Guido van Rossum00d93061998-05-28 23:06:38 +0000314
Guido van Rossum18468821994-06-20 07:49:28 +0000315static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000316AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000317{
Guido van Rossum35d43371997-08-02 00:09:09 +0000318 if (PyString_Check(value))
319 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000320#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000321 else if (PyUnicode_Check(value)) {
322 PyObject *v = PyUnicode_AsUTF8String(value);
323 if (v == NULL)
324 return NULL;
325 if (PyList_Append(tmp, v) != 0) {
326 Py_DECREF(v);
327 return NULL;
328 }
329 Py_DECREF(v);
330 return PyString_AsString(v);
331 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000332#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000333 else {
334 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000335 if (v == NULL)
336 return NULL;
337 if (PyList_Append(tmp, v) != 0) {
338 Py_DECREF(v);
339 return NULL;
340 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000341 Py_DECREF(v);
342 return PyString_AsString(v);
343 }
Guido van Rossum18468821994-06-20 07:49:28 +0000344}
345
Barry Warsawfa701a81997-01-16 00:15:11 +0000346
347
Guido van Rossum18468821994-06-20 07:49:28 +0000348#define ARGSZ 64
349
350static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000351Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000352{
Barry Warsawfa701a81997-01-16 00:15:11 +0000353 PyObject *tmp = NULL;
354 char *argvStore[ARGSZ];
355 char **argv = NULL;
356 int fvStore[ARGSZ];
357 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000358 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000359 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000360
Barry Warsawfa701a81997-01-16 00:15:11 +0000361 if (!(tmp = PyList_New(0)))
362 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000363
Barry Warsawfa701a81997-01-16 00:15:11 +0000364 argv = argvStore;
365 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000366
Barry Warsawfa701a81997-01-16 00:15:11 +0000367 if (args == NULL)
368 argc = 0;
369
370 else if (!PyTuple_Check(args)) {
371 argc = 1;
372 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000373 if (!(argv[0] = AsString(args, tmp)))
374 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000375 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000376 else {
377 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000378
Barry Warsawfa701a81997-01-16 00:15:11 +0000379 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000380 argv = (char **)ckalloc(argc * sizeof(char *));
381 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000382 if (argv == NULL || fv == NULL) {
383 PyErr_NoMemory();
384 goto finally;
385 }
386 }
387
388 for (i = 0; i < argc; i++) {
389 PyObject *v = PyTuple_GetItem(args, i);
390 if (PyTuple_Check(v)) {
391 fv[i] = 1;
392 if (!(argv[i] = Merge(v)))
393 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000394 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000395 }
396 else if (v == Py_None) {
397 argc = i;
398 break;
399 }
400 else {
401 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000402 if (!(argv[i] = AsString(v, tmp)))
403 goto finally;
404 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000405 }
406 }
Guido van Rossum18468821994-06-20 07:49:28 +0000407 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000408 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000409 if (res == NULL)
410 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000411
Barry Warsawfa701a81997-01-16 00:15:11 +0000412 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000413 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000414 if (fv[i]) {
415 ckfree(argv[i]);
416 }
417 if (argv != argvStore)
418 ckfree(FREECAST argv);
419 if (fv != fvStore)
420 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000421
Barry Warsawfa701a81997-01-16 00:15:11 +0000422 Py_DECREF(tmp);
423 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000424}
425
Barry Warsawfa701a81997-01-16 00:15:11 +0000426
427
Guido van Rossum18468821994-06-20 07:49:28 +0000428static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000429Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000430{
Barry Warsawfa701a81997-01-16 00:15:11 +0000431 int argc;
432 char **argv;
433 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000434
Barry Warsawfa701a81997-01-16 00:15:11 +0000435 if (list == NULL) {
436 Py_INCREF(Py_None);
437 return Py_None;
438 }
Guido van Rossum18468821994-06-20 07:49:28 +0000439
Guido van Rossum00d93061998-05-28 23:06:38 +0000440 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000441 /* Not a list.
442 * Could be a quoted string containing funnies, e.g. {"}.
443 * Return the string itself.
444 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000445 return PyString_FromString(list);
446 }
Guido van Rossum18468821994-06-20 07:49:28 +0000447
Barry Warsawfa701a81997-01-16 00:15:11 +0000448 if (argc == 0)
449 v = PyString_FromString("");
450 else if (argc == 1)
451 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000452 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000453 int i;
454 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000455
Barry Warsawfa701a81997-01-16 00:15:11 +0000456 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000457 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000458 Py_DECREF(v);
459 v = NULL;
460 break;
461 }
462 PyTuple_SetItem(v, i, w);
463 }
464 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000465 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000466 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000467}
468
Martin v. Löwisffad6332002-11-26 09:28:05 +0000469/* In some cases, Tcl will still return strings that are supposed to be
470 lists. SplitObj walks through a nested tuple, finding string objects that
471 need to be split. */
472
473PyObject *
474SplitObj(PyObject *arg)
475{
476 if (PyTuple_Check(arg)) {
477 int i, size;
478 PyObject *elem, *newelem, *result;
479
480 size = PyTuple_Size(arg);
481 result = NULL;
482 /* Recursively invoke SplitObj for all tuple items.
483 If this does not return a new object, no action is
484 needed. */
485 for(i = 0; i < size; i++) {
486 elem = PyTuple_GetItem(arg, i);
487 newelem = SplitObj(elem);
488 if (!newelem) {
489 Py_XDECREF(result);
490 return NULL;
491 }
492 if (!result) {
493 int k;
494 if (newelem == elem) {
495 Py_DECREF(newelem);
496 continue;
497 }
498 result = PyTuple_New(size);
499 if (!result)
500 return NULL;
501 for(k = 0; k < i; k++) {
502 elem = PyTuple_GetItem(arg, k);
503 Py_INCREF(elem);
504 PyTuple_SetItem(result, k, elem);
505 }
506 }
507 PyTuple_SetItem(result, i, newelem);
508 }
509 if (result)
510 return result;
511 /* Fall through, returning arg. */
512 }
513 else if (PyString_Check(arg)) {
514 int argc;
515 char **argv;
516 char *list = PyString_AsString(arg);
517
518 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
519 Py_INCREF(arg);
520 return arg;
521 }
522 Tcl_Free(FREECAST argv);
523 if (argc > 1)
524 return Split(PyString_AsString(arg));
525 /* Fall through, returning arg. */
526 }
527 Py_INCREF(arg);
528 return arg;
529}
Barry Warsawfa701a81997-01-16 00:15:11 +0000530
531
Guido van Rossum18468821994-06-20 07:49:28 +0000532/**** Tkapp Object ****/
533
534#ifndef WITH_APPINIT
535int
Fred Drake509d79a2000-07-08 04:04:38 +0000536Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000537{
Barry Warsawfa701a81997-01-16 00:15:11 +0000538 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000539
Barry Warsawfa701a81997-01-16 00:15:11 +0000540 main = Tk_MainWindow(interp);
541 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000542 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000543 return TCL_ERROR;
544 }
545 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000546 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000547 return TCL_ERROR;
548 }
549 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000550}
551#endif /* !WITH_APPINIT */
552
Guido van Rossum18468821994-06-20 07:49:28 +0000553
Barry Warsawfa701a81997-01-16 00:15:11 +0000554
555
556/* Initialize the Tk application; see the `main' function in
557 * `tkMain.c'.
558 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000559
Thomas Wouters58d05102000-07-24 14:43:35 +0000560static void EnableEventHook(void); /* Forward */
561static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000562
Barry Warsawfa701a81997-01-16 00:15:11 +0000563static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000564Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000565 int interactive, int wantobjects)
Barry Warsawfa701a81997-01-16 00:15:11 +0000566{
567 TkappObject *v;
568 char *argv0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000569
Guido van Rossumb18618d2000-05-03 23:44:39 +0000570 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000571 if (v == NULL)
572 return NULL;
573
574 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000575 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000576 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
577 TCL_GLOBAL_ONLY) != NULL;
578 v->thread_id = Tcl_GetCurrentThread();
579 v->dispatching = 0;
580
581#ifndef TCL_THREADS
582 if (v->threaded) {
583 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
584 Py_DECREF(v);
585 return 0;
586 }
587#endif
588 if (v->threaded && tcl_lock) {
589 /* If Tcl is threaded, we don't need the lock. */
590 PyThread_free_lock(tcl_lock);
591 tcl_lock = NULL;
592 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000593
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000594 v->BooleanType = Tcl_GetObjType("boolean");
595 v->ByteArrayType = Tcl_GetObjType("bytearray");
596 v->DoubleType = Tcl_GetObjType("double");
597 v->IntType = Tcl_GetObjType("int");
598 v->ListType = Tcl_GetObjType("list");
599 v->ProcBodyType = Tcl_GetObjType("procbody");
600 v->StringType = Tcl_GetObjType("string");
601
Guido van Rossuma80649b2000-03-28 20:07:05 +0000602#if defined(macintosh)
603 /* This seems to be needed */
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000604 ClearMenuBar();
605 TkMacInitMenus(v->interp);
606#endif
Jack Jansencb852442001-12-09 23:15:56 +0000607
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000608 /* Delete the 'exit' command, which can screw things up */
609 Tcl_DeleteCommand(v->interp, "exit");
610
Barry Warsawfa701a81997-01-16 00:15:11 +0000611 if (screenName != NULL)
612 Tcl_SetVar2(v->interp, "env", "DISPLAY",
613 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000614
Barry Warsawfa701a81997-01-16 00:15:11 +0000615 if (interactive)
616 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
617 else
618 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000619
Barry Warsawfa701a81997-01-16 00:15:11 +0000620 /* This is used to get the application class for Tk 4.1 and up */
621 argv0 = (char*)ckalloc(strlen(className) + 1);
622 if (!argv0) {
623 PyErr_NoMemory();
624 Py_DECREF(v);
625 return NULL;
626 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000627
Barry Warsawfa701a81997-01-16 00:15:11 +0000628 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000629 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000630 argv0[0] = tolower(argv0[0]);
631 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
632 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000633
Barry Warsawfa701a81997-01-16 00:15:11 +0000634 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000635 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000636
Guido van Rossum7bf15641998-05-22 18:28:17 +0000637 EnableEventHook();
638
Barry Warsawfa701a81997-01-16 00:15:11 +0000639 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000640}
641
Barry Warsawfa701a81997-01-16 00:15:11 +0000642
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000643static void
644Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
645 Tcl_Condition *cond, Tcl_Mutex *mutex)
646{
647 Py_BEGIN_ALLOW_THREADS;
648 Tcl_MutexLock(mutex);
649 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
650 Tcl_ThreadAlert(self->thread_id);
651 Tcl_ConditionWait(cond, mutex, NULL);
652 Tcl_MutexUnlock(mutex);
653 Py_END_ALLOW_THREADS
654}
655
Barry Warsawfa701a81997-01-16 00:15:11 +0000656
Guido van Rossum18468821994-06-20 07:49:28 +0000657/** Tcl Eval **/
658
Martin v. Löwisffad6332002-11-26 09:28:05 +0000659typedef struct {
660 PyObject_HEAD
661 Tcl_Obj *value;
662} PyTclObject;
663
664staticforward PyTypeObject PyTclObject_Type;
665#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
666
667static PyObject *
668newPyTclObject(Tcl_Obj *arg)
669{
670 PyTclObject *self;
671 self = PyObject_New(PyTclObject, &PyTclObject_Type);
672 if (self == NULL)
673 return NULL;
674 Tcl_IncrRefCount(arg);
675 self->value = arg;
676 return (PyObject*)self;
677}
678
679static void
680PyTclObject_dealloc(PyTclObject *self)
681{
682 Tcl_DecrRefCount(self->value);
683 PyObject_Del(self);
684}
685
686static PyObject *
687PyTclObject_str(PyTclObject *self)
688{
689 return PyString_FromString(Tcl_GetString(self->value));
690}
691
692static PyObject *
693PyTclObject_repr(PyTclObject *self)
694{
695 char buf[50];
696 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
697 self->value->typePtr->name, (int)self->value);
698 return PyString_FromString(buf);
699}
700
701static PyObject*
702get_typename(PyTclObject* obj, void* ignored)
703{
704 return PyString_FromString(obj->value->typePtr->name);
705}
706
707static PyGetSetDef PyTclObject_getsetlist[] = {
708 {"typename", (getter)get_typename, NULL, "name of the Tcl type"},
709 {0},
710};
711
712statichere PyTypeObject PyTclObject_Type = {
713 PyObject_HEAD_INIT(NULL)
714 0, /*ob_size*/
715 "_tkinter.Tcl_Obj", /*tp_name*/
716 sizeof(PyTclObject), /*tp_basicsize*/
717 0, /*tp_itemsize*/
718 /* methods */
719 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
720 0, /*tp_print*/
721 0, /*tp_getattr*/
722 0, /*tp_setattr*/
723 0, /*tp_compare*/
724 (reprfunc)PyTclObject_repr, /*tp_repr*/
725 0, /*tp_as_number*/
726 0, /*tp_as_sequence*/
727 0, /*tp_as_mapping*/
728 0, /*tp_hash*/
729 0, /*tp_call*/
730 (reprfunc)PyTclObject_str, /*tp_str*/
731 PyObject_GenericGetAttr,/*tp_getattro*/
732 0, /*tp_setattro*/
733 0, /*tp_as_buffer*/
734 Py_TPFLAGS_DEFAULT, /*tp_flags*/
735 0, /*tp_doc*/
736 0, /*tp_traverse*/
737 0, /*tp_clear*/
738 0, /*tp_richcompare*/
739 0, /*tp_weaklistoffset*/
740 0, /*tp_iter*/
741 0, /*tp_iternext*/
742 0, /*tp_methods*/
743 0, /*tp_members*/
744 PyTclObject_getsetlist, /*tp_getset*/
745 0, /*tp_base*/
746 0, /*tp_dict*/
747 0, /*tp_descr_get*/
748 0, /*tp_descr_set*/
749 0, /*tp_dictoffset*/
750 0, /*tp_init*/
751 0, /*tp_alloc*/
752 0, /*tp_new*/
753 0, /*tp_free*/
754 0, /*tp_is_gc*/
755};
756
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000757static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000758AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000759{
760 Tcl_Obj *result;
761
762 if (PyString_Check(value))
763 return Tcl_NewStringObj(PyString_AS_STRING(value),
764 PyString_GET_SIZE(value));
765 else if (PyInt_Check(value))
766 return Tcl_NewLongObj(PyInt_AS_LONG(value));
767 else if (PyFloat_Check(value))
768 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
769 else if (PyTuple_Check(value)) {
770 Tcl_Obj **argv = (Tcl_Obj**)
771 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
772 int i;
773 if(!argv)
774 return 0;
775 for(i=0;i<PyTuple_Size(value);i++)
776 argv[i] = AsObj(PyTuple_GetItem(value,i));
777 result = Tcl_NewListObj(PyTuple_Size(value), argv);
778 ckfree(FREECAST argv);
779 return result;
780 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000781#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000782 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000783 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
784 int size = PyUnicode_GET_SIZE(value);
785 /* This #ifdef assumes that Tcl uses UCS-2.
786 See TCL_UTF_MAX test above. */
787#ifdef Py_UNICODE_WIDE
788 Tcl_UniChar *outbuf;
789 int i;
790 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
791 if (!outbuf) {
792 PyErr_NoMemory();
793 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000794 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000795 for (i = 0; i < size; i++) {
796 if (inbuf[i] >= 0x10000) {
797 /* Tcl doesn't do UTF-16, yet. */
798 PyErr_SetString(PyExc_ValueError,
799 "unsupported character");
800 ckfree(FREECAST outbuf);
801 return NULL;
802 }
803 outbuf[i] = inbuf[i];
804 }
805 result = Tcl_NewUnicodeObj(outbuf, size);
806 ckfree(FREECAST outbuf);
807 return result;
808#else
809 return Tcl_NewUnicodeObj(inbuf, size);
810#endif
811
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000812 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000813#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000814 else if(PyTclObject_Check(value)) {
815 Tcl_Obj *v = ((PyTclObject*)value)->value;
816 Tcl_IncrRefCount(v);
817 return v;
818 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000819 else {
820 PyObject *v = PyObject_Str(value);
821 if (!v)
822 return 0;
823 result = AsObj(v);
824 Py_DECREF(v);
825 return result;
826 }
827}
828
Martin v. Löwisffad6332002-11-26 09:28:05 +0000829static PyObject*
830FromObj(PyObject* tkapp, Tcl_Obj *value)
831{
832 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000833 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000834
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000835 if (value->typePtr == NULL) {
836 /* If the result contains any bytes with the top bit set,
837 it's UTF-8 and we should decode it to Unicode */
838#ifdef Py_USING_UNICODE
839 int i;
840 char *s = value->bytes;
841 int len = value->length;
842 for (i = 0; i < len; i++) {
843 if (value->bytes[i] & 0x80)
844 break;
845 }
846
847 if (i == value->length)
848 result = PyString_FromStringAndSize(s, len);
849 else {
850 /* Convert UTF-8 to Unicode string */
851 result = PyUnicode_DecodeUTF8(s, len, "strict");
852 if (result == NULL) {
853 PyErr_Clear();
854 result = PyString_FromStringAndSize(s, len);
855 }
856 }
857#else
858 res = PyString_FromStringAndSize(value->bytes, value->length);
859#endif
860 return result;
861 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000862
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000863 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000864 result = value->internalRep.longValue ? Py_True : Py_False;
865 Py_INCREF(result);
866 return result;
867 }
868
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000869 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000870 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000871 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000872 return PyString_FromStringAndSize(data, size);
873 }
874
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000875 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000876 return PyFloat_FromDouble(value->internalRep.doubleValue);
877 }
878
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000879 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000880 return PyInt_FromLong(value->internalRep.longValue);
881 }
882
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000883 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000884 int size;
885 int i, status;
886 PyObject *elem;
887 Tcl_Obj *tcl_elem;
888
889 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
890 if (status == TCL_ERROR)
891 return Tkinter_Error(tkapp);
892 result = PyTuple_New(size);
893 if (!result)
894 return NULL;
895 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000896 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +0000897 value, i, &tcl_elem);
898 if (status == TCL_ERROR) {
899 Py_DECREF(result);
900 return Tkinter_Error(tkapp);
901 }
902 elem = FromObj(tkapp, tcl_elem);
903 if (!elem) {
904 Py_DECREF(result);
905 return NULL;
906 }
907 PyTuple_SetItem(result, i, elem);
908 }
909 return result;
910 }
911
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000912 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000913 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000914 }
915
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000916 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000917#ifdef Py_USING_UNICODE
918#ifdef Py_UNICODE_WIDE
919 PyObject *result;
920 int size;
921 Tcl_UniChar *input;
922 Py_UNICODE *output;
923
924 size = Tcl_GetCharLength(value);
925 result = PyUnicode_FromUnicode(NULL, size);
926 if (!result)
927 return NULL;
928 input = Tcl_GetUnicode(value);
929 output = PyUnicode_AS_UNICODE(result);
930 while (size--)
931 *output++ = *input++;
932 return result;
933#else
934 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
935 Tcl_GetCharLength(value));
936#endif
937#else
938 int size;
939 char *c;
940 c = Tcl_GetStringFromObj(value, &size);
941 return PyString_FromStringAndSize(c, size);
942#endif
943 }
944
945 return newPyTclObject(value);
946}
947
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000948/* This mutex synchronizes inter-thread command calls. */
949
950TCL_DECLARE_MUTEX(call_mutex)
951
952typedef struct Tkapp_CallEvent {
953 Tcl_Event ev; /* Must be first */
954 TkappObject *self;
955 PyObject *args;
956 int flags;
957 PyObject **res;
958 PyObject **exc_type, **exc_value, **exc_tb;
959 Tcl_Condition done;
960} Tkapp_CallEvent;
961
962void
963Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +0000964{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000965 int i;
966 for (i = 0; i < objc; i++)
967 Tcl_DecrRefCount(objv[i]);
968 if (objv != objStore)
969 ckfree(FREECAST objv);
970}
Guido van Rossum18468821994-06-20 07:49:28 +0000971
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000972/* Convert Python objects to Tcl objects. This must happen in the
973 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +0000974
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000975static Tcl_Obj**
976Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
977{
978 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +0000979 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +0000980 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +0000981 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +0000982
Guido van Rossum212643f1998-04-29 16:22:14 +0000983 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +0000984 objv[0] = AsObj(args);
985 if (objv[0] == 0)
986 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +0000987 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +0000988 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +0000989 }
990 else {
Guido van Rossum632de272000-03-29 00:19:50 +0000991 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +0000992
Guido van Rossum632de272000-03-29 00:19:50 +0000993 if (objc > ARGSZ) {
994 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
995 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +0000996 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +0000997 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +0000998 goto finally;
999 }
1000 }
1001
Guido van Rossum632de272000-03-29 00:19:50 +00001002 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001003 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001004 if (v == Py_None) {
1005 objc = i;
1006 break;
1007 }
Guido van Rossum632de272000-03-29 00:19:50 +00001008 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001009 if (!objv[i]) {
1010 /* Reset objc, so it attempts to clear
1011 objects only up to i. */
1012 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001013 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001014 }
Guido van Rossum632de272000-03-29 00:19:50 +00001015 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001016 }
1017 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001018 *pobjc = objc;
1019 return objv;
1020finally:
1021 Tkapp_CallDeallocArgs(objv, objStore, objc);
1022 return NULL;
1023}
Guido van Rossum212643f1998-04-29 16:22:14 +00001024
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001025/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001026
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001027static PyObject*
1028Tkapp_CallResult(TkappObject *self)
1029{
1030 PyObject *res = NULL;
1031 if(self->wantobjects) {
1032 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001033 /* Not sure whether the IncrRef is necessary, but something
1034 may overwrite the interpreter result while we are
1035 converting it. */
1036 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001037 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001038 Tcl_DecrRefCount(value);
1039 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001040 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001041 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001042
Guido van Rossum990f5c62000-05-04 15:07:16 +00001043 /* If the result contains any bytes with the top bit set,
1044 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001045#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001046 while (*p != '\0') {
1047 if (*p & 0x80)
1048 break;
1049 p++;
1050 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001051
Guido van Rossum990f5c62000-05-04 15:07:16 +00001052 if (*p == '\0')
1053 res = PyString_FromStringAndSize(s, (int)(p-s));
1054 else {
1055 /* Convert UTF-8 to Unicode string */
1056 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001057 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1058 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001059 PyErr_Clear();
1060 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001061 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001062 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001063#else
1064 p = strchr(p, '\0');
1065 res = PyString_FromStringAndSize(s, (int)(p-s));
1066#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001067 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001068 return res;
1069}
Guido van Rossum632de272000-03-29 00:19:50 +00001070
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001071/* Tkapp_CallProc is the event procedure that is executed in the context of
1072 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1073 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001074
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001075static int
1076Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1077{
1078 Tcl_Obj *objStore[ARGSZ];
1079 Tcl_Obj **objv;
1080 int objc;
1081 int i;
1082 ENTER_PYTHON
1083 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1084 if (!objv) {
1085 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1086 *(e->res) = NULL;
1087 }
1088 LEAVE_PYTHON
1089 if (!objv)
1090 goto done;
1091 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1092 ENTER_PYTHON
1093 if (i == TCL_ERROR) {
1094 *(e->res) = NULL;
1095 *(e->exc_type) = NULL;
1096 *(e->exc_tb) = NULL;
1097 *(e->exc_value) = PyObject_CallFunction(
1098 Tkinter_TclError, "s",
1099 Tcl_GetStringResult(e->self->interp));
1100 }
1101 else {
1102 *(e->res) = Tkapp_CallResult(e->self);
1103 }
1104 LEAVE_PYTHON
1105 done:
1106 /* Wake up calling thread. */
1107 Tcl_MutexLock(&call_mutex);
1108 Tcl_ConditionNotify(&e->done);
1109 Tcl_MutexUnlock(&call_mutex);
1110 return 1;
1111}
1112
1113/* This is the main entry point for calling a Tcl command.
1114 It supports three cases, with regard to threading:
1115 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1116 the context of the calling thread.
1117 2. Tcl is threaded, caller of the command is in the interpreter thread:
1118 Execute the command in the calling thread. Since the Tcl lock will
1119 not be used, we can merge that with case 1.
1120 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1121 the interpreter thread. Allocation of Tcl objects needs to occur in the
1122 interpreter thread, so we ship the PyObject* args to the target thread,
1123 and perform processing there. */
1124
1125static PyObject *
1126Tkapp_Call(PyObject *_self, PyObject *args)
1127{
1128 Tcl_Obj *objStore[ARGSZ];
1129 Tcl_Obj **objv = NULL;
1130 int objc, i;
1131 PyObject *res = NULL;
1132 TkappObject *self = (TkappObject*)_self;
1133 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1134 int flags = TCL_EVAL_DIRECT;
1135
1136 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1137 /* We cannot call the command directly. Instead, we must
1138 marshal the parameters to the interpreter thread. */
1139 Tkapp_CallEvent *ev;
1140 PyObject *exc_type, *exc_value, *exc_tb;
1141 if (!self->dispatching) {
1142 PyErr_SetString(PyExc_RuntimeError,
1143 "main thread is not in main loop");
1144 return NULL;
1145 }
1146 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1147 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1148 ev->self = self;
1149 ev->args = args;
1150 ev->res = &res;
1151 ev->exc_type = &exc_type;
1152 ev->exc_value = &exc_value;
1153 ev->exc_tb = &exc_tb;
1154 ev->done = (Tcl_Condition)0;
1155
1156 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1157
1158 if (res == NULL) {
1159 if (exc_type)
1160 PyErr_Restore(exc_type, exc_value, exc_tb);
1161 else
1162 PyErr_SetObject(Tkinter_TclError, exc_value);
1163 }
1164 }
1165 else {
1166
1167 objv = Tkapp_CallArgs(args, objStore, &objc);
1168 if (!objv)
1169 return NULL;
1170
1171 ENTER_TCL
1172
1173 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1174
1175 ENTER_OVERLAP
1176
1177 if (i == TCL_ERROR)
1178 Tkinter_Error(_self);
1179 else
1180 res = Tkapp_CallResult(self);
1181
1182 LEAVE_OVERLAP_TCL
1183
1184 Tkapp_CallDeallocArgs(objv, objStore, objc);
1185 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001186 return res;
1187}
1188
1189
1190static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001191Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001192{
Guido van Rossum212643f1998-04-29 16:22:14 +00001193 /* Could do the same here as for Tkapp_Call(), but this is not used
1194 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1195 way for the user to do what all its Global* variants do (save and
1196 reset the scope pointer, call the local version, restore the saved
1197 scope pointer). */
1198
Guido van Rossum62320c91998-06-15 04:36:09 +00001199 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001200 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001201
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001202 CHECK_TCL_APPARTMENT;
1203
Guido van Rossum62320c91998-06-15 04:36:09 +00001204 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001205 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001206 int err;
1207 ENTER_TCL
1208 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001209 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001210 if (err == TCL_ERROR)
1211 res = Tkinter_Error(self);
1212 else
1213 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001214 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001215 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001216 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001217
1218 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001219}
1220
1221static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001222Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001223{
Barry Warsawfa701a81997-01-16 00:15:11 +00001224 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001225 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001226 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001227
Guido van Rossum43713e52000-02-29 13:59:29 +00001228 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001229 return NULL;
1230
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001231 CHECK_TCL_APPARTMENT;
1232
Guido van Rossum00d93061998-05-28 23:06:38 +00001233 ENTER_TCL
1234 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001235 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001236 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001237 res = Tkinter_Error(self);
1238 else
1239 res = PyString_FromString(Tkapp_Result(self));
1240 LEAVE_OVERLAP_TCL
1241 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001242}
1243
1244static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001245Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001246{
Barry Warsawfa701a81997-01-16 00:15:11 +00001247 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001248 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001249 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001250
Guido van Rossum43713e52000-02-29 13:59:29 +00001251 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001252 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001253
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001254 CHECK_TCL_APPARTMENT;
1255
Guido van Rossum00d93061998-05-28 23:06:38 +00001256 ENTER_TCL
1257 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001258 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001259 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001260 res = Tkinter_Error(self);
1261 else
1262 res = PyString_FromString(Tkapp_Result(self));
1263 LEAVE_OVERLAP_TCL
1264 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001265}
1266
1267static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001268Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001269{
Barry Warsawfa701a81997-01-16 00:15:11 +00001270 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001271 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001272 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001273
Guido van Rossum43713e52000-02-29 13:59:29 +00001274 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001275 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001276
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001277 CHECK_TCL_APPARTMENT;
1278
Guido van Rossum00d93061998-05-28 23:06:38 +00001279 ENTER_TCL
1280 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001281 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001282 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001283 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001284
Guido van Rossum62320c91998-06-15 04:36:09 +00001285 else
1286 res = PyString_FromString(Tkapp_Result(self));
1287 LEAVE_OVERLAP_TCL
1288 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001289}
1290
1291static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001292Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001293{
Barry Warsawfa701a81997-01-16 00:15:11 +00001294 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001295 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001296 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001297
Guido van Rossum35d43371997-08-02 00:09:09 +00001298 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001299 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001300
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001301 CHECK_TCL_APPARTMENT;
1302
Guido van Rossum00d93061998-05-28 23:06:38 +00001303 ENTER_TCL
1304 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001305 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001306 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001307 res = Tkinter_Error(self);
1308 else
1309 res = PyString_FromString(Tkapp_Result(self));
1310 LEAVE_OVERLAP_TCL
1311 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001312}
1313
1314static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001315Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001316{
Barry Warsawfa701a81997-01-16 00:15:11 +00001317 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001318
Guido van Rossum43713e52000-02-29 13:59:29 +00001319 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001320 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001321 CHECK_TCL_APPARTMENT;
1322
Guido van Rossum00d93061998-05-28 23:06:38 +00001323 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001324 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001325 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001326
Barry Warsawfa701a81997-01-16 00:15:11 +00001327 Py_INCREF(Py_None);
1328 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001329}
1330
Barry Warsawfa701a81997-01-16 00:15:11 +00001331
1332
Guido van Rossum18468821994-06-20 07:49:28 +00001333/** Tcl Variable **/
1334
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001335TCL_DECLARE_MUTEX(var_mutex)
1336
1337typedef const char* (*EventFunc1)(Tcl_Interp*, const char*, int);
1338typedef const char* (*EventFunc2)(Tcl_Interp*, const char*, const char*, int);
1339typedef const char* (*EventFunc3)(Tcl_Interp*, const char*, const char*, const char*, int);
1340typedef struct VarEvent {
1341 Tcl_Event ev; /* must be first */
1342 TkappObject *self;
1343 char* arg1;
1344 char* arg2;
1345 char* arg3;
1346 int flags;
1347 EventFunc1 func1;
1348 EventFunc2 func2;
1349 EventFunc3 func3;
1350 PyObject **res;
1351 PyObject **exc;
1352 Tcl_Condition cond;
1353 int coderesult;
1354} VarEvent;
1355
1356static const char*
1357var_perform(VarEvent *ev)
1358{
1359 if (!ev->arg2 && !ev->arg2)
1360 return ev->func1(ev->self->interp, ev->arg1, ev->flags);
1361 if (!ev->arg3)
1362 return ev->func2(ev->self->interp, ev->arg1,
1363 ev->arg2, ev->flags);
1364 return ev->func3(ev->self->interp, ev->arg1, ev->arg2,
1365 ev->arg3, ev->flags);
1366}
1367
1368static void
1369var_fill_result(VarEvent *ev, const char* res)
1370{
1371 if (ev->coderesult) {
1372 if ((int)res != TCL_ERROR) {
1373 Py_INCREF(Py_None);
1374 *(ev->res) = Py_None;
1375 return;
1376 }
1377 }
1378 else if (res) {
1379 *(ev->res) = PyString_FromString(res);
1380 return;
1381 }
1382
1383 *(ev->res) = NULL;
1384 *(ev->exc) = PyObject_CallFunction(
1385 Tkinter_TclError, "s",
1386 Tcl_GetStringResult(ev->self->interp));
1387
1388}
1389
1390static int
1391var_proc(VarEvent* ev, int flags)
1392{
1393 const char *result = var_perform(ev);
1394 ENTER_PYTHON
1395 var_fill_result(ev, result);
1396 Tcl_MutexLock(&var_mutex);
1397 Tcl_ConditionNotify(&ev->cond);
1398 Tcl_MutexUnlock(&var_mutex);
1399 LEAVE_PYTHON
1400 return 1;
1401}
1402
1403static PyObject*
1404var_invoke(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
1405 EventFunc1 func1, EventFunc2 func2, EventFunc3 func3,
1406 int coderesult)
1407{
1408 VarEvent _ev;
1409 TkappObject *self = (TkappObject*)_self;
1410 VarEvent *ev = self->threaded ?
1411 (VarEvent*)ckalloc(sizeof(VarEvent)) : &_ev;
1412 PyObject *res, *exc;
1413
1414 ev->self = self;
1415 ev->arg1 = arg1;
1416 ev->arg2 = arg2;
1417 ev->arg3 = arg3;
1418 ev->flags = flags;
1419 ev->func1 = func1;
1420 ev->func2 = func2;
1421 ev->func3 = func3;
1422 ev->coderesult = coderesult;
1423 ev->res = &res;
1424 ev->exc = &exc;
1425 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1426 /* The current thread is not the interpreter thread. Marshal
1427 the call to the interpreter thread, then wait for
1428 completion. */
1429
1430 if (!self->dispatching) {
1431 PyErr_SetString(PyExc_RuntimeError,
1432 "main thread is not in main loop");
1433 return NULL;
1434 }
1435 ev->cond = NULL;
1436 ev->ev.proc = (Tcl_EventProc*)var_proc;
1437 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1438 }
1439 else {
1440 /* Tcl is not threaded, or this is the interpreter thread. To
1441 perform the call, we must hold the TCL lock. To receive the
1442 results, we must also hold the Python lock. */
1443 const char *result;
1444 ENTER_TCL
1445 result = var_perform(ev);
1446 ENTER_OVERLAP
1447 var_fill_result(ev, result);
1448 LEAVE_OVERLAP_TCL
1449 }
1450 if (!res) {
1451 PyErr_SetObject(Tkinter_TclError, exc);
1452 return NULL;
1453 }
1454 return res;
1455}
1456
1457static PyObject*
1458var_invoke2(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
1459 int (*func1)(Tcl_Interp*, const char*, int),
1460 int (*func2)(Tcl_Interp*, const char*, const char*, int),
1461 int (*func3)(Tcl_Interp*, const char*, const char*, const char*, int))
1462{
1463 return var_invoke(_self, arg1, arg2, arg3, flags,
1464 (EventFunc1)func1, (EventFunc2)func2,
1465 (EventFunc3)func3, 1);
1466}
1467
Guido van Rossum18468821994-06-20 07:49:28 +00001468static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001469SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001470{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001471 char *name1, *name2, *s;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001472 PyObject *res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001473 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +00001474 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +00001475
Guido van Rossum62320c91998-06-15 04:36:09 +00001476 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +00001477 if (!tmp)
1478 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001479
Guido van Rossum43713e52000-02-29 13:59:29 +00001480 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001481 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +00001482 s = AsString(newValue, tmp);
Guido van Rossum2834b972000-10-06 16:58:26 +00001483 if (s == NULL)
1484 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001485 res = var_invoke(self, name1, s, NULL, flags,
1486 NULL, Tcl_SetVar, NULL, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001487 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001488 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001489 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001490 if (PyArg_ParseTuple(args, "ssO:setvar",
1491 &name1, &name2, &newValue)) {
1492 s = AsString(newValue, tmp);
1493 if (s == NULL)
1494 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001495 res = var_invoke(self, name1, name2, s, flags,
1496 NULL, NULL, Tcl_SetVar2, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001497 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001498 else {
Guido van Rossum00d93061998-05-28 23:06:38 +00001499 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +00001500 return NULL;
1501 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001502 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001503 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +00001504
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001505 if (!res)
1506 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001507
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001508 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001509 Py_INCREF(Py_None);
1510 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001511}
1512
1513static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001514Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001515{
Barry Warsawfa701a81997-01-16 00:15:11 +00001516 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001517}
1518
1519static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001520Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001521{
Barry Warsawfa701a81997-01-16 00:15:11 +00001522 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001523}
1524
Barry Warsawfa701a81997-01-16 00:15:11 +00001525
1526
Guido van Rossum18468821994-06-20 07:49:28 +00001527static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001528GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001529{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001530 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001531 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001532
Guido van Rossum43713e52000-02-29 13:59:29 +00001533 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001534 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001535
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536 res = var_invoke(self, name1, name2, NULL, flags,
1537 Tcl_GetVar, Tcl_GetVar2, NULL, 0);
Guido van Rossum62320c91998-06-15 04:36:09 +00001538 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001539}
1540
1541static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001542Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001543{
Barry Warsawfa701a81997-01-16 00:15:11 +00001544 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001545}
1546
1547static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001548Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001549{
Barry Warsawfa701a81997-01-16 00:15:11 +00001550 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001551}
1552
Barry Warsawfa701a81997-01-16 00:15:11 +00001553
1554
Guido van Rossum18468821994-06-20 07:49:28 +00001555static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001556UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001557{
Guido van Rossum35d43371997-08-02 00:09:09 +00001558 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001559 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001560
Guido van Rossum43713e52000-02-29 13:59:29 +00001561 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001562 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001563
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001564 res = var_invoke2(self, name1, name2, NULL, flags,
1565 Tcl_UnsetVar, Tcl_UnsetVar2, NULL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001566 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001567}
1568
1569static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001570Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001571{
Barry Warsawfa701a81997-01-16 00:15:11 +00001572 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001573}
1574
1575static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001576Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001577{
Barry Warsawfa701a81997-01-16 00:15:11 +00001578 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001579}
1580
Barry Warsawfa701a81997-01-16 00:15:11 +00001581
1582
Guido van Rossum18468821994-06-20 07:49:28 +00001583/** Tcl to Python **/
1584
1585static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001586Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001587{
Barry Warsawfa701a81997-01-16 00:15:11 +00001588 char *s;
1589 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001590
Martin v. Löwisffad6332002-11-26 09:28:05 +00001591 if (PyTuple_Size(args) == 1) {
1592 PyObject* o = PyTuple_GetItem(args, 0);
1593 if (PyInt_Check(o)) {
1594 Py_INCREF(o);
1595 return o;
1596 }
1597 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001598 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001599 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001600 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001601 return Tkinter_Error(self);
1602 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001603}
1604
1605static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001606Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001607{
Barry Warsawfa701a81997-01-16 00:15:11 +00001608 char *s;
1609 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001610
Martin v. Löwisffad6332002-11-26 09:28:05 +00001611 if (PyTuple_Size(args) == 1) {
1612 PyObject *o = PyTuple_GetItem(args, 0);
1613 if (PyFloat_Check(o)) {
1614 Py_INCREF(o);
1615 return o;
1616 }
1617 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001618 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001619 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001620 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001621 return Tkinter_Error(self);
1622 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001623}
1624
1625static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001626Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001627{
Barry Warsawfa701a81997-01-16 00:15:11 +00001628 char *s;
1629 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001630
Martin v. Löwisffad6332002-11-26 09:28:05 +00001631 if (PyTuple_Size(args) == 1) {
1632 PyObject *o = PyTuple_GetItem(args, 0);
1633 if (PyInt_Check(o)) {
1634 Py_INCREF(o);
1635 return o;
1636 }
1637 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001638 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001639 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001640 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1641 return Tkinter_Error(self);
Barry Warsawfa701a81997-01-16 00:15:11 +00001642 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001643}
1644
1645static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001646Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001647{
Barry Warsawfa701a81997-01-16 00:15:11 +00001648 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001649 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001650 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001651
Guido van Rossum43713e52000-02-29 13:59:29 +00001652 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001653 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001654
1655 CHECK_TCL_APPARTMENT;
1656
Guido van Rossum00d93061998-05-28 23:06:38 +00001657 ENTER_TCL
1658 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001659 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001660 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001661 res = Tkinter_Error(self);
1662 else
1663 res = Py_BuildValue("s", Tkapp_Result(self));
1664 LEAVE_OVERLAP_TCL
1665 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001666}
1667
1668static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001669Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001670{
Barry Warsawfa701a81997-01-16 00:15:11 +00001671 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001672 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001673 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001674 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001675
Guido van Rossum43713e52000-02-29 13:59:29 +00001676 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001677 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001678
1679 CHECK_TCL_APPARTMENT;
1680
Guido van Rossum00d93061998-05-28 23:06:38 +00001681 ENTER_TCL
1682 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001683 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001684 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001685 res = Tkinter_Error(self);
1686 else
1687 res = Py_BuildValue("l", v);
1688 LEAVE_OVERLAP_TCL
1689 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001690}
1691
1692static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001693Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001694{
Barry Warsawfa701a81997-01-16 00:15:11 +00001695 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001696 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001697 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001698 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001699
Guido van Rossum43713e52000-02-29 13:59:29 +00001700 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001701 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001702 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001703 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001704 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001705 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001706 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001707 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001708 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001709 res = Tkinter_Error(self);
1710 else
1711 res = Py_BuildValue("d", v);
1712 LEAVE_OVERLAP_TCL
1713 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001714}
1715
1716static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001717Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001718{
Barry Warsawfa701a81997-01-16 00:15:11 +00001719 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001720 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001721 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001722 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001723
Guido van Rossum43713e52000-02-29 13:59:29 +00001724 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001725 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001726 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001727 ENTER_TCL
1728 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001729 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001730 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001731 res = Tkinter_Error(self);
1732 else
1733 res = Py_BuildValue("i", v);
1734 LEAVE_OVERLAP_TCL
1735 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001736}
1737
Barry Warsawfa701a81997-01-16 00:15:11 +00001738
1739
Guido van Rossum18468821994-06-20 07:49:28 +00001740static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001741Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001742{
Barry Warsawfa701a81997-01-16 00:15:11 +00001743 char *list;
1744 int argc;
1745 char **argv;
1746 PyObject *v;
1747 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001748
Martin v. Löwisffad6332002-11-26 09:28:05 +00001749 if (PyTuple_Size(args) == 1) {
1750 v = PyTuple_GetItem(args, 0);
1751 if (PyTuple_Check(v)) {
1752 Py_INCREF(v);
1753 return v;
1754 }
1755 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001756 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001757 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001758
Barry Warsawfa701a81997-01-16 00:15:11 +00001759 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1760 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001761
Barry Warsawfa701a81997-01-16 00:15:11 +00001762 if (!(v = PyTuple_New(argc)))
1763 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001764
Barry Warsawfa701a81997-01-16 00:15:11 +00001765 for (i = 0; i < argc; i++) {
1766 PyObject *s = PyString_FromString(argv[i]);
1767 if (!s || PyTuple_SetItem(v, i, s)) {
1768 Py_DECREF(v);
1769 v = NULL;
1770 goto finally;
1771 }
1772 }
Guido van Rossum18468821994-06-20 07:49:28 +00001773
Barry Warsawfa701a81997-01-16 00:15:11 +00001774 finally:
1775 ckfree(FREECAST argv);
1776 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001777}
1778
1779static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001780Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001781{
Barry Warsawfa701a81997-01-16 00:15:11 +00001782 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001783
Martin v. Löwisffad6332002-11-26 09:28:05 +00001784 if (PyTuple_Size(args) == 1) {
1785 PyObject* o = PyTuple_GetItem(args, 0);
1786 if (PyTuple_Check(o)) {
1787 o = SplitObj(o);
1788 return o;
1789 }
1790 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001791 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001792 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001793 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001794}
1795
1796static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001797Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001798{
Barry Warsawfa701a81997-01-16 00:15:11 +00001799 char *s = Merge(args);
1800 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001801
Barry Warsawfa701a81997-01-16 00:15:11 +00001802 if (s) {
1803 res = PyString_FromString(s);
1804 ckfree(s);
1805 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001806
1807 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001808}
1809
Barry Warsawfa701a81997-01-16 00:15:11 +00001810
1811
Guido van Rossum18468821994-06-20 07:49:28 +00001812/** Tcl Command **/
1813
Guido van Rossum00d93061998-05-28 23:06:38 +00001814/* Client data struct */
1815typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001816 PyObject *self;
1817 PyObject *func;
1818} PythonCmd_ClientData;
1819
1820static int
Fred Drake509d79a2000-07-08 04:04:38 +00001821PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001822{
1823 errorInCmd = 1;
1824 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1825 LEAVE_PYTHON
1826 return TCL_ERROR;
1827}
1828
Guido van Rossum18468821994-06-20 07:49:28 +00001829/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001830 * function or method.
1831 */
Guido van Rossum18468821994-06-20 07:49:28 +00001832static int
Fred Drake509d79a2000-07-08 04:04:38 +00001833PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001834{
Guido van Rossum00d93061998-05-28 23:06:38 +00001835 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001836 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001837 int i, rv;
1838 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001839
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001840 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001841
Barry Warsawfa701a81997-01-16 00:15:11 +00001842 /* TBD: no error checking here since we know, via the
1843 * Tkapp_CreateCommand() that the client data is a two-tuple
1844 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001845 self = data->self;
1846 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001847
Barry Warsawfa701a81997-01-16 00:15:11 +00001848 /* Create argument list (argv1, ..., argvN) */
1849 if (!(arg = PyTuple_New(argc - 1)))
1850 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001851
Barry Warsawfa701a81997-01-16 00:15:11 +00001852 for (i = 0; i < (argc - 1); i++) {
1853 PyObject *s = PyString_FromString(argv[i + 1]);
1854 if (!s || PyTuple_SetItem(arg, i, s)) {
1855 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001856 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001857 }
1858 }
1859 res = PyEval_CallObject(func, arg);
1860 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001861
Barry Warsawfa701a81997-01-16 00:15:11 +00001862 if (res == NULL)
1863 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001864
Barry Warsawfa701a81997-01-16 00:15:11 +00001865 if (!(tmp = PyList_New(0))) {
1866 Py_DECREF(res);
1867 return PythonCmd_Error(interp);
1868 }
1869
Guido van Rossum2834b972000-10-06 16:58:26 +00001870 s = AsString(res, tmp);
1871 if (s == NULL) {
1872 rv = PythonCmd_Error(interp);
1873 }
1874 else {
1875 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1876 rv = TCL_OK;
1877 }
1878
Barry Warsawfa701a81997-01-16 00:15:11 +00001879 Py_DECREF(res);
1880 Py_DECREF(tmp);
1881
Guido van Rossum00d93061998-05-28 23:06:38 +00001882 LEAVE_PYTHON
1883
Guido van Rossum2834b972000-10-06 16:58:26 +00001884 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001885}
1886
1887static void
Fred Drake509d79a2000-07-08 04:04:38 +00001888PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001889{
Guido van Rossum00d93061998-05-28 23:06:38 +00001890 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1891
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001892 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001893 Py_XDECREF(data->self);
1894 Py_XDECREF(data->func);
1895 PyMem_DEL(data);
1896 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001897}
1898
Barry Warsawfa701a81997-01-16 00:15:11 +00001899
1900
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001901
1902TCL_DECLARE_MUTEX(command_mutex)
1903
1904typedef struct CommandEvent{
1905 Tcl_Event ev;
1906 Tcl_Interp* interp;
1907 char *name;
1908 int create;
1909 int *status;
1910 ClientData *data;
1911 Tcl_Condition done;
1912} CommandEvent;
1913
1914static int
1915Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001916{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001917 if (ev->create)
1918 *ev->status = Tcl_CreateCommand(
1919 ev->interp, ev->name, PythonCmd,
1920 ev->data, PythonCmdDelete) == NULL;
1921 else
1922 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1923 Tcl_MutexLock(&command_mutex);
1924 Tcl_ConditionNotify(&ev->done);
1925 Tcl_MutexUnlock(&command_mutex);
1926 return 1;
1927}
1928
1929static PyObject *
1930Tkapp_CreateCommand(PyObject *_self, PyObject *args)
1931{
1932 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001933 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001934 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00001935 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001936 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001937
Guido van Rossum43713e52000-02-29 13:59:29 +00001938 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00001939 return NULL;
1940 if (!PyCallable_Check(func)) {
1941 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00001942 return NULL;
1943 }
Guido van Rossum18468821994-06-20 07:49:28 +00001944
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001945 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
1946 !self->dispatching) {
1947 PyErr_SetString(PyExc_RuntimeError,
1948 "main thread is not in main loop");
1949 return NULL;
1950 }
1951
Guido van Rossum00d93061998-05-28 23:06:38 +00001952 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00001953 if (!data)
1954 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001955 Py_XINCREF(self);
1956 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001957 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001958 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001959
1960 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1961 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
1962 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
1963 ev->interp = self->interp;
1964 ev->create = 1;
1965 ev->name = cmdName;
1966 ev->data = (ClientData)data;
1967 ev->status = &err;
1968 ev->done = NULL;
1969 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
1970 }
1971 else {
1972 ENTER_TCL
1973 err = Tcl_CreateCommand(
1974 Tkapp_Interp(self), cmdName, PythonCmd,
1975 (ClientData)data, PythonCmdDelete) == NULL;
1976 LEAVE_TCL
1977 }
1978 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001979 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00001980 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00001981 return NULL;
1982 }
Guido van Rossum18468821994-06-20 07:49:28 +00001983
Barry Warsawfa701a81997-01-16 00:15:11 +00001984 Py_INCREF(Py_None);
1985 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001986}
1987
Barry Warsawfa701a81997-01-16 00:15:11 +00001988
1989
Guido van Rossum18468821994-06-20 07:49:28 +00001990static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001991Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001992{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001993 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00001994 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00001995 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001996
Guido van Rossum43713e52000-02-29 13:59:29 +00001997 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001998 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001999 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2000 CommandEvent *ev;
2001 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2002 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2003 ev->interp = self->interp;
2004 ev->create = 0;
2005 ev->name = cmdName;
2006 ev->status = &err;
2007 ev->done = NULL;
2008 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2009 &command_mutex);
2010 }
2011 else {
2012 ENTER_TCL
2013 err = Tcl_DeleteCommand(self->interp, cmdName);
2014 LEAVE_TCL
2015 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002016 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002017 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2018 return NULL;
2019 }
2020 Py_INCREF(Py_None);
2021 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002022}
2023
Barry Warsawfa701a81997-01-16 00:15:11 +00002024
2025
Guido van Rossum00d93061998-05-28 23:06:38 +00002026#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002027/** File Handler **/
2028
Guido van Rossum00d93061998-05-28 23:06:38 +00002029typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002030 PyObject *func;
2031 PyObject *file;
2032 int id;
2033 struct _fhcdata *next;
2034} FileHandler_ClientData;
2035
2036static FileHandler_ClientData *HeadFHCD;
2037
2038static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002039NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002040{
2041 FileHandler_ClientData *p;
2042 p = PyMem_NEW(FileHandler_ClientData, 1);
2043 if (p != NULL) {
2044 Py_XINCREF(func);
2045 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002046 p->func = func;
2047 p->file = file;
2048 p->id = id;
2049 p->next = HeadFHCD;
2050 HeadFHCD = p;
2051 }
2052 return p;
2053}
2054
2055static void
Fred Drake509d79a2000-07-08 04:04:38 +00002056DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002057{
2058 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002059
2060 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002061 while ((p = *pp) != NULL) {
2062 if (p->id == id) {
2063 *pp = p->next;
2064 Py_XDECREF(p->func);
2065 Py_XDECREF(p->file);
2066 PyMem_DEL(p);
2067 }
2068 else
2069 pp = &p->next;
2070 }
2071}
2072
Guido van Rossuma597dde1995-01-10 20:56:29 +00002073static void
Fred Drake509d79a2000-07-08 04:04:38 +00002074FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002075{
Guido van Rossum00d93061998-05-28 23:06:38 +00002076 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002077 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002078
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002079 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002080 func = data->func;
2081 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002082
Barry Warsawfa701a81997-01-16 00:15:11 +00002083 arg = Py_BuildValue("(Oi)", file, (long) mask);
2084 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002085 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002086
2087 if (res == NULL) {
2088 errorInCmd = 1;
2089 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2090 }
2091 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002092 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002093}
2094
Guido van Rossum18468821994-06-20 07:49:28 +00002095static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002096Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2097 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002098{
Guido van Rossum00d93061998-05-28 23:06:38 +00002099 FileHandler_ClientData *data;
2100 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002101 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002102
Guido van Rossum2834b972000-10-06 16:58:26 +00002103 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2104 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002105 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002106 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002107 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002108 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002109 return NULL;
2110 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002111 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002112 return NULL;
2113 }
2114
Guido van Rossuma80649b2000-03-28 20:07:05 +00002115 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002116 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002117 return NULL;
2118
Barry Warsawfa701a81997-01-16 00:15:11 +00002119 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002120 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002121 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002122 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002123 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002124 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002125}
2126
2127static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002128Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002129{
Barry Warsawfa701a81997-01-16 00:15:11 +00002130 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002131 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002132
Guido van Rossum43713e52000-02-29 13:59:29 +00002133 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002134 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002135 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002136 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002137 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002138 return NULL;
2139
Guido van Rossuma80649b2000-03-28 20:07:05 +00002140 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002141
Barry Warsawfa701a81997-01-16 00:15:11 +00002142 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002143 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002144 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002145 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002146 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002147 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002148}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002149#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002150
Barry Warsawfa701a81997-01-16 00:15:11 +00002151
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002152/**** Tktt Object (timer token) ****/
2153
Jeremy Hylton938ace62002-07-17 16:30:39 +00002154static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002155
Guido van Rossum00d93061998-05-28 23:06:38 +00002156typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002157 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002158 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002159 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002160} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002161
2162static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002163Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002164{
Barry Warsawfa701a81997-01-16 00:15:11 +00002165 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002166 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002167
Guido van Rossum43713e52000-02-29 13:59:29 +00002168 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002169 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002170 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002171 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002172 v->token = NULL;
2173 }
2174 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002175 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002176 Py_DECREF(func);
2177 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002178 }
2179 Py_INCREF(Py_None);
2180 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002181}
2182
2183static PyMethodDef Tktt_methods[] =
2184{
Neal Norwitzb0493252002-03-31 14:44:22 +00002185 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002186 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002187};
2188
2189static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002190Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002191{
Barry Warsawfa701a81997-01-16 00:15:11 +00002192 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002193
Guido van Rossumb18618d2000-05-03 23:44:39 +00002194 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002195 if (v == NULL)
2196 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002197
Guido van Rossum00d93061998-05-28 23:06:38 +00002198 Py_INCREF(func);
2199 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002200 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002201
2202 /* Extra reference, deleted when called or when handler is deleted */
2203 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002204 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002205}
2206
2207static void
Fred Drake509d79a2000-07-08 04:04:38 +00002208Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002209{
Guido van Rossum00d93061998-05-28 23:06:38 +00002210 TkttObject *v = (TkttObject *)self;
2211 PyObject *func = v->func;
2212
2213 Py_XDECREF(func);
2214
Guido van Rossumb18618d2000-05-03 23:44:39 +00002215 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002216}
2217
Guido van Rossum597ac201998-05-12 14:36:19 +00002218static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002219Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002220{
Barry Warsawfa701a81997-01-16 00:15:11 +00002221 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002222 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002223
Tim Peters885d4572001-11-28 20:27:42 +00002224 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002225 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002226 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002227}
2228
2229static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002230Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002231{
Barry Warsawfa701a81997-01-16 00:15:11 +00002232 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002233}
2234
2235static PyTypeObject Tktt_Type =
2236{
Guido van Rossum35d43371997-08-02 00:09:09 +00002237 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002238 0, /*ob_size */
2239 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002240 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002241 0, /*tp_itemsize */
2242 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002243 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002244 Tktt_GetAttr, /*tp_getattr */
2245 0, /*tp_setattr */
2246 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002247 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002248 0, /*tp_as_number */
2249 0, /*tp_as_sequence */
2250 0, /*tp_as_mapping */
2251 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002252};
2253
Barry Warsawfa701a81997-01-16 00:15:11 +00002254
2255
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002256/** Timer Handler **/
2257
2258static void
Fred Drake509d79a2000-07-08 04:04:38 +00002259TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002260{
Guido van Rossum00d93061998-05-28 23:06:38 +00002261 TkttObject *v = (TkttObject *)clientData;
2262 PyObject *func = v->func;
2263 PyObject *res;
2264
2265 if (func == NULL)
2266 return;
2267
2268 v->func = NULL;
2269
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002270 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002271
2272 res = PyEval_CallObject(func, NULL);
2273 Py_DECREF(func);
2274 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002275
Barry Warsawfa701a81997-01-16 00:15:11 +00002276 if (res == NULL) {
2277 errorInCmd = 1;
2278 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2279 }
2280 else
2281 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002282
2283 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002284}
2285
2286static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002287Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002288{
Barry Warsawfa701a81997-01-16 00:15:11 +00002289 int milliseconds;
2290 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002291 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002292
Guido van Rossum2834b972000-10-06 16:58:26 +00002293 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2294 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002295 return NULL;
2296 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002297 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002298 return NULL;
2299 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002300 v = Tktt_New(func);
2301 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2302 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002303
Guido van Rossum00d93061998-05-28 23:06:38 +00002304 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002305}
2306
Barry Warsawfa701a81997-01-16 00:15:11 +00002307
Guido van Rossum18468821994-06-20 07:49:28 +00002308/** Event Loop **/
2309
Guido van Rossum18468821994-06-20 07:49:28 +00002310static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002311Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002312{
Barry Warsawfa701a81997-01-16 00:15:11 +00002313 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002314 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002315#ifdef WITH_THREAD
2316 PyThreadState *tstate = PyThreadState_Get();
2317#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002318
Guido van Rossum43713e52000-02-29 13:59:29 +00002319 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002320 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002321
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002322 CHECK_TCL_APPARTMENT;
2323
Barry Warsawfa701a81997-01-16 00:15:11 +00002324 quitMainLoop = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002325 self->dispatching = 1;
Barry Warsawfa701a81997-01-16 00:15:11 +00002326 while (Tk_GetNumMainWindows() > threshold &&
2327 !quitMainLoop &&
2328 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002329 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002330 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002331
2332#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002333 if (self->threaded) {
2334 /* Allow other Python threads to run. */
2335 ENTER_TCL
2336 result = Tcl_DoOneEvent(0);
2337 LEAVE_TCL
2338 }
2339 else {
2340 Py_BEGIN_ALLOW_THREADS
2341 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2342 tcl_tstate = tstate;
2343 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2344 tcl_tstate = NULL;
2345 if(tcl_lock)PyThread_release_lock(tcl_lock);
2346 if (result == 0)
2347 Sleep(20);
2348 Py_END_ALLOW_THREADS
2349 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002350#else
2351 result = Tcl_DoOneEvent(0);
2352#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002353
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002354 if (PyErr_CheckSignals() != 0) {
2355 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002356 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002357 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002358 if (result < 0)
2359 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002360 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002361 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002362 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002363
Barry Warsawfa701a81997-01-16 00:15:11 +00002364 if (errorInCmd) {
2365 errorInCmd = 0;
2366 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2367 excInCmd = valInCmd = trbInCmd = NULL;
2368 return NULL;
2369 }
2370 Py_INCREF(Py_None);
2371 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002372}
2373
2374static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002375Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002376{
Guido van Rossum35d43371997-08-02 00:09:09 +00002377 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002378 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002379
Guido van Rossum43713e52000-02-29 13:59:29 +00002380 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002381 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002382 CHECK_TCL_APPARTMENT;
Barry Warsawfa701a81997-01-16 00:15:11 +00002383
Guido van Rossum00d93061998-05-28 23:06:38 +00002384 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002385 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002386 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002387 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002388}
2389
2390static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002391Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002392{
2393
Guido van Rossum43713e52000-02-29 13:59:29 +00002394 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002395 return NULL;
2396
2397 quitMainLoop = 1;
2398 Py_INCREF(Py_None);
2399 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002400}
2401
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002402static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002403Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002404{
2405
Guido van Rossum43713e52000-02-29 13:59:29 +00002406 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002407 return NULL;
2408
2409 return PyInt_FromLong((long)Tkapp_Interp(self));
2410}
2411
Barry Warsawfa701a81997-01-16 00:15:11 +00002412
Martin v. Löwisffad6332002-11-26 09:28:05 +00002413static PyObject *
2414Tkapp_WantObjects(PyObject *self, PyObject *args)
2415{
2416
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002417 int wantobjects;
2418 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002419 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002420 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002421
2422 Py_INCREF(Py_None);
2423 return Py_None;
2424}
2425
2426
Barry Warsawfa701a81997-01-16 00:15:11 +00002427
Guido van Rossum18468821994-06-20 07:49:28 +00002428/**** Tkapp Method List ****/
2429
2430static PyMethodDef Tkapp_methods[] =
2431{
Martin v. Löwisffad6332002-11-26 09:28:05 +00002432 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002433 {"call", Tkapp_Call, METH_OLDARGS},
2434 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2435 {"eval", Tkapp_Eval, METH_VARARGS},
2436 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2437 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2438 {"record", Tkapp_Record, METH_VARARGS},
2439 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2440 {"setvar", Tkapp_SetVar, METH_VARARGS},
2441 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2442 {"getvar", Tkapp_GetVar, METH_VARARGS},
2443 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2444 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2445 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2446 {"getint", Tkapp_GetInt, METH_VARARGS},
2447 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2448 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2449 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2450 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2451 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2452 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2453 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2454 {"split", Tkapp_Split, METH_VARARGS},
2455 {"merge", Tkapp_Merge, METH_OLDARGS},
2456 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2457 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002458#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002459 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2460 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002461#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002462 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2463 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2464 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2465 {"quit", Tkapp_Quit, METH_VARARGS},
2466 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002467 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002468};
2469
Barry Warsawfa701a81997-01-16 00:15:11 +00002470
2471
Guido van Rossum18468821994-06-20 07:49:28 +00002472/**** Tkapp Type Methods ****/
2473
2474static void
Fred Drake509d79a2000-07-08 04:04:38 +00002475Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002476{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002477 //CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00002478 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002479 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002480 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002481 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002482 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002483}
2484
2485static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002486Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002487{
Guido van Rossum35d43371997-08-02 00:09:09 +00002488 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002489}
2490
2491static PyTypeObject Tkapp_Type =
2492{
Guido van Rossum35d43371997-08-02 00:09:09 +00002493 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002494 0, /*ob_size */
2495 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002496 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002497 0, /*tp_itemsize */
2498 Tkapp_Dealloc, /*tp_dealloc */
2499 0, /*tp_print */
2500 Tkapp_GetAttr, /*tp_getattr */
2501 0, /*tp_setattr */
2502 0, /*tp_compare */
2503 0, /*tp_repr */
2504 0, /*tp_as_number */
2505 0, /*tp_as_sequence */
2506 0, /*tp_as_mapping */
2507 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002508};
2509
Barry Warsawfa701a81997-01-16 00:15:11 +00002510
2511
Guido van Rossum18468821994-06-20 07:49:28 +00002512/**** Tkinter Module ****/
2513
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002514typedef struct {
2515 PyObject* tuple;
2516 int size; /* current size */
2517 int maxsize; /* allocated size */
2518} FlattenContext;
2519
2520static int
2521_bump(FlattenContext* context, int size)
2522{
Guido van Rossum2834b972000-10-06 16:58:26 +00002523 /* expand tuple to hold (at least) size new items.
2524 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002525
2526 int maxsize = context->maxsize * 2;
2527
2528 if (maxsize < context->size + size)
2529 maxsize = context->size + size;
2530
2531 context->maxsize = maxsize;
2532
Tim Peters4324aa32001-05-28 22:30:08 +00002533 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002534}
2535
2536static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002537_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002538{
2539 /* add tuple or list to argument tuple (recursively) */
2540
2541 int i, size;
2542
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002543 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002544 PyErr_SetString(PyExc_ValueError,
2545 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002546 return 0;
2547 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002548 size = PyList_GET_SIZE(item);
2549 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002550 if (context->size + size > context->maxsize &&
2551 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002552 return 0;
2553 /* copy items to output tuple */
2554 for (i = 0; i < size; i++) {
2555 PyObject *o = PyList_GET_ITEM(item, i);
2556 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002557 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002558 return 0;
2559 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002560 if (context->size + 1 > context->maxsize &&
2561 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002562 return 0;
2563 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002564 PyTuple_SET_ITEM(context->tuple,
2565 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002566 }
2567 }
2568 } else if (PyTuple_Check(item)) {
2569 /* same, for tuples */
2570 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002571 if (context->size + size > context->maxsize &&
2572 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002573 return 0;
2574 for (i = 0; i < size; i++) {
2575 PyObject *o = PyTuple_GET_ITEM(item, i);
2576 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002577 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002578 return 0;
2579 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002580 if (context->size + 1 > context->maxsize &&
2581 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002582 return 0;
2583 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002584 PyTuple_SET_ITEM(context->tuple,
2585 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002586 }
2587 }
2588 } else {
2589 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2590 return 0;
2591 }
2592 return 1;
2593}
2594
2595static PyObject *
2596Tkinter_Flatten(PyObject* self, PyObject* args)
2597{
2598 FlattenContext context;
2599 PyObject* item;
2600
2601 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2602 return NULL;
2603
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002604 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002605 if (context.maxsize <= 0)
2606 return PyTuple_New(0);
2607
2608 context.tuple = PyTuple_New(context.maxsize);
2609 if (!context.tuple)
2610 return NULL;
2611
2612 context.size = 0;
2613
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002614 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002615 return NULL;
2616
Tim Peters4324aa32001-05-28 22:30:08 +00002617 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002618 return NULL;
2619
2620 return context.tuple;
2621}
2622
Guido van Rossum18468821994-06-20 07:49:28 +00002623static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002624Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002625{
Barry Warsawfa701a81997-01-16 00:15:11 +00002626 char *screenName = NULL;
2627 char *baseName = NULL;
2628 char *className = NULL;
2629 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002630 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002631
Guido van Rossum35d43371997-08-02 00:09:09 +00002632 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002633 if (baseName != NULL)
2634 baseName++;
2635 else
2636 baseName = Py_GetProgramName();
2637 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002638
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002639 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002640 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002641 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002642 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002643
Barry Warsawfa701a81997-01-16 00:15:11 +00002644 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002645 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002646}
2647
2648static PyMethodDef moduleMethods[] =
2649{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002650 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2651 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002652#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002653 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2654 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002655#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002656 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2657 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2658 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2659 {"quit", Tkapp_Quit, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002660 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002661};
2662
Guido van Rossum7bf15641998-05-22 18:28:17 +00002663#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002664
2665static int stdin_ready = 0;
2666
Guido van Rossumad4db171998-06-13 13:56:28 +00002667#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002668static void
Fred Drake509d79a2000-07-08 04:04:38 +00002669MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002670{
2671 stdin_ready = 1;
2672}
Guido van Rossumad4db171998-06-13 13:56:28 +00002673#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002674
Guido van Rossum00d93061998-05-28 23:06:38 +00002675static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002676
Guido van Rossum18468821994-06-20 07:49:28 +00002677static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002678EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002679{
Guido van Rossumad4db171998-06-13 13:56:28 +00002680#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002681 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002682#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002683#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002684 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002685#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002686 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002687 errorInCmd = 0;
2688#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002689 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002690 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002691#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002692 while (!errorInCmd && !stdin_ready) {
2693 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002694#ifdef MS_WINDOWS
2695 if (_kbhit()) {
2696 stdin_ready = 1;
2697 break;
2698 }
2699#endif
2700#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002701 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002702 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002703 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002704
Guido van Rossum00d93061998-05-28 23:06:38 +00002705 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002706
2707 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002708 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002709 if (result == 0)
2710 Sleep(20);
2711 Py_END_ALLOW_THREADS
2712#else
2713 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002714#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002715
2716 if (result < 0)
2717 break;
2718 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002719#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002720 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002721#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002722 if (errorInCmd) {
2723 errorInCmd = 0;
2724 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2725 excInCmd = valInCmd = trbInCmd = NULL;
2726 PyErr_Print();
2727 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002728#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002729 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002730#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002731 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002732}
Guido van Rossum18468821994-06-20 07:49:28 +00002733
Guido van Rossum00d93061998-05-28 23:06:38 +00002734#endif
2735
Guido van Rossum7bf15641998-05-22 18:28:17 +00002736static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002737EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002738{
Guido van Rossum00d93061998-05-28 23:06:38 +00002739#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002740 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002741#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002742 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002743#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002744 PyOS_InputHook = EventHook;
2745 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002746#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002747}
2748
2749static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002750DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002751{
Guido van Rossum00d93061998-05-28 23:06:38 +00002752#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002753 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2754 PyOS_InputHook = NULL;
2755 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002756#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002757}
2758
Barry Warsawfa701a81997-01-16 00:15:11 +00002759
2760/* all errors will be checked in one fell swoop in init_tkinter() */
2761static void
Fred Drake509d79a2000-07-08 04:04:38 +00002762ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002763{
2764 PyObject *v = PyInt_FromLong(val);
2765 if (v) {
2766 PyDict_SetItemString(d, name, v);
2767 Py_DECREF(v);
2768 }
2769}
2770static void
Fred Drake509d79a2000-07-08 04:04:38 +00002771ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002772{
2773 PyObject *v = PyString_FromString(val);
2774 if (v) {
2775 PyDict_SetItemString(d, name, v);
2776 Py_DECREF(v);
2777 }
2778}
2779
2780
Mark Hammond62b1ab12002-07-23 06:31:15 +00002781PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002782init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002783{
Barry Warsawfa701a81997-01-16 00:15:11 +00002784 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002785
Barry Warsawfa701a81997-01-16 00:15:11 +00002786 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002787
2788#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002789 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002790#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002791
Barry Warsawfa701a81997-01-16 00:15:11 +00002792 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002793
Barry Warsawfa701a81997-01-16 00:15:11 +00002794 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00002795 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00002796 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002797
Guido van Rossum35d43371997-08-02 00:09:09 +00002798 ins_long(d, "READABLE", TCL_READABLE);
2799 ins_long(d, "WRITABLE", TCL_WRITABLE);
2800 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2801 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2802 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2803 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2804 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2805 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2806 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002807 ins_string(d, "TK_VERSION", TK_VERSION);
2808 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002809
Guido van Rossum83551bf1997-09-13 00:44:23 +00002810 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002811
2812 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002813 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2814
Martin v. Löwisffad6332002-11-26 09:28:05 +00002815 PyTclObject_Type.ob_type = &PyType_Type;
2816 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002817
2818#ifdef TK_AQUA
2819 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2820 * start waking up. Note that Tcl_FindExecutable will do this, this
2821 * code must be above it! The original warning from
2822 * tkMacOSXAppInit.c is copied below.
2823 *
2824 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2825 * Tcl interpreter for now. It probably should work to do this
2826 * in the other order, but for now it doesn't seem to.
2827 *
2828 */
2829 Tk_MacOSXSetupTkNotifier();
2830#endif
2831
2832
Guido van Rossume187b0e2000-03-27 21:46:29 +00002833 /* This helps the dynamic loader; in Unicode aware Tcl versions
2834 it also helps Tcl find its encodings. */
2835 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00002836
Barry Warsawfa701a81997-01-16 00:15:11 +00002837 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002838 return;
2839
Guido van Rossum43ff8681998-07-14 18:02:13 +00002840#if 0
2841 /* This was not a good idea; through <Destroy> bindings,
2842 Tcl_Finalize() may invoke Python code but at that point the
2843 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002844 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002845#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002846
Jack Jansen34cc5c31995-10-31 16:15:12 +00002847#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002848 /*
2849 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2850 ** Most of the initializations in that routine (toolbox init calls and
2851 ** such) have already been done for us, so we only need these.
2852 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002853 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002854
2855 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00002856#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00002857 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00002858#endif /* GENERATINGCFM */
2859#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00002860}
Guido van Rossum9722ad81995-09-22 23:49:28 +00002861
Guido van Rossumec22c921996-02-25 04:50:29 +00002862
Barry Warsawfa701a81997-01-16 00:15:11 +00002863
Guido van Rossum9722ad81995-09-22 23:49:28 +00002864#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002865
2866/*
Guido van Rossumec22c921996-02-25 04:50:29 +00002867** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002868*/
2869
Guido van Rossum9722ad81995-09-22 23:49:28 +00002870void
2871panic(char * format, ...)
2872{
Barry Warsawfa701a81997-01-16 00:15:11 +00002873 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002874
Barry Warsawfa701a81997-01-16 00:15:11 +00002875 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002876
Guido van Rossum227cf761998-08-05 13:53:32 +00002877 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002878 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002879
Barry Warsawfa701a81997-01-16 00:15:11 +00002880 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002881
Barry Warsawfa701a81997-01-16 00:15:11 +00002882 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00002883}
Jack Jansen40b546d1995-11-14 10:34:45 +00002884
Guido van Rossumec22c921996-02-25 04:50:29 +00002885/*
2886** Pass events to SIOUX before passing them to Tk.
2887*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002888
Guido van Rossumec22c921996-02-25 04:50:29 +00002889static int
Fred Drake509d79a2000-07-08 04:04:38 +00002890PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002891{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002892 WindowPtr frontwin;
2893 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00002894 ** Sioux eats too many events, so we don't pass it everything. We
2895 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002896 ** the Sioux window is frontmost. This means that Tk menus don't work
2897 ** in that case, but at least we can scroll the sioux window.
2898 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2899 ** part of the external interface of Sioux...
2900 */
2901 frontwin = FrontWindow();
2902 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
2903 if (SIOUXHandleOneEvent(eventPtr))
2904 return 0; /* Nothing happened to the Tcl event queue */
2905 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002906 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002907}
2908
Guido van Rossumec22c921996-02-25 04:50:29 +00002909#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002910
2911/*
2912** Additional Mac specific code for dealing with shared libraries.
2913*/
2914
2915#include <Resources.h>
2916#include <CodeFragments.h>
2917
2918static int loaded_from_shlib = 0;
2919static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002920
Jack Jansen34cc5c31995-10-31 16:15:12 +00002921/*
2922** If this module is dynamically loaded the following routine should
2923** be the init routine. It takes care of adding the shared library to
2924** the resource-file chain, so that the tk routines can find their
2925** resources.
2926*/
2927OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002928init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002929{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00002930 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00002931 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002932 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002933 library_fss = *data->fragLocator.u.onDisk.fileSpec;
2934 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002935 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002936 library_fss = *data->fragLocator.u.inSegs.fileSpec;
2937 loaded_from_shlib = 1;
2938 }
2939 return noErr;
2940}
2941
2942/*
2943** Insert the library resources into the search path. Put them after
2944** the resources from the application. Again, we ignore errors.
2945*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002946static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002947mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002948{
2949 if ( !loaded_from_shlib )
2950 return;
2951 (void)FSpOpenResFile(&library_fss, fsRdPerm);
2952}
2953
Guido van Rossumec22c921996-02-25 04:50:29 +00002954#endif /* GENERATINGCFM */
2955#endif /* macintosh */