blob: f617088e9dac93cc6129d7209c2d0180b79196a5 [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
Martin v. Löwis5b177f12002-12-30 18:14:15 +000060/* For Tcl 8.2 and 8.3, CONST* is not defined. */
61#ifndef CONST84_RETURN
62#define CONST84_RETURN
63#define CONST
64#endif
65
Guido van Rossum3e819a71997-08-01 19:29:02 +000066#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
67
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000068#if TKMAJORMINOR < 8002
69#error "Tk older than 8.2 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000070#endif
71
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000072/* Unicode conversion assumes that Tcl_UniChar is two bytes.
73 We cannot test this directly, so we test UTF-8 size instead,
74 expecting that TCL_UTF_MAX is changed if Tcl ever supports
75 either UTF-16 or UCS-4. */
76#if TCL_UTF_MAX != 3
77#error "unsupported Tcl configuration"
78#endif
79
Guido van Rossuma80649b2000-03-28 20:07:05 +000080#if defined(macintosh)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000081/* Sigh, we have to include this to get at the tcl qd pointer */
82#include <tkMac.h>
Guido van Rossum2ea1c941998-04-28 16:12:43 +000083/* And this one we need to clear the menu bar */
84#include <Menus.h>
Guido van Rossum0d2390c1997-08-14 19:57:07 +000085#endif
86
Jack Jansen84c10b12001-07-16 19:32:52 +000087#if !(defined(MS_WINDOWS) || defined(__CYGWIN__) || defined(macintosh))
88/* Mac has it, but it doesn't really work:-( */
Guido van Rossum0d2390c1997-08-14 19:57:07 +000089#define HAVE_CREATEFILEHANDLER
90#endif
91
Guido van Rossum00d93061998-05-28 23:06:38 +000092#ifdef HAVE_CREATEFILEHANDLER
93
94/* Tcl_CreateFileHandler() changed several times; these macros deal with the
95 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
96 Unix, only because Jack added it back); when available on Windows, it only
97 applies to sockets. */
98
Guido van Rossum7bf15641998-05-22 18:28:17 +000099#ifdef MS_WINDOWS
100#define FHANDLETYPE TCL_WIN_SOCKET
101#else
102#define FHANDLETYPE TCL_UNIX_FD
103#endif
104
Guido van Rossum00d93061998-05-28 23:06:38 +0000105/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
106 which uses this to handle Tcl events while the user is typing commands. */
107
108#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000109#define WAIT_FOR_STDIN
110#endif
111
Guido van Rossum00d93061998-05-28 23:06:38 +0000112#endif /* HAVE_CREATEFILEHANDLER */
113
Guido van Rossumad4db171998-06-13 13:56:28 +0000114#ifdef MS_WINDOWS
115#include <conio.h>
116#define WAIT_FOR_STDIN
117#endif
118
Guido van Rossum00d93061998-05-28 23:06:38 +0000119#ifdef WITH_THREAD
120
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000121/* The threading situation is complicated. Tcl is not thread-safe, except
122 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000123 So we need to use a lock around all uses of Tcl. Previously, the Python
124 interpreter lock was used for this. However, this causes problems when
125 other Python threads need to run while Tcl is blocked waiting for events.
126
127 To solve this problem, a separate lock for Tcl is introduced. Holding it
128 is incompatible with holding Python's interpreter lock. The following four
129 macros manipulate both locks together.
130
131 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
132 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
133 that could call an event handler, or otherwise affect the state of a Tcl
134 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000135 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000136 released and the lock for Tcl has been acquired.
137
Guido van Rossum5e977831998-06-15 14:03:52 +0000138 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
139 (For example, when transferring data from the Tcl interpreter result to a
140 Python string object.) This can be done by using different macros to close
141 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
142 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
143 releases the Tcl lock.
144
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000145 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000146 handlers when the handler needs to use Python. Such event handlers are
147 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000148 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000149 the Python interpreter lock, restoring the appropriate thread state, and
150 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
151 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000152 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000153
154 These locks expand to several statements and brackets; they should not be
155 used in branches of if statements and the like.
156
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000157 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
158 only valid in the thread that created it, and all Tk activity must happen in this
159 thread, also. That means that the mainloop must be invoked in the thread that
160 created the interpreter. Invoking commands from other threads is possible;
161 _tkinter will queue an event for the interpreter thread, which will then
162 execute the command and pass back the result. If the main thread is not in the
163 mainloop, and invoking commands causes an exception; if the main loop is running
164 but not processing events, the command invocation will block.
165
166 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
167 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
168 threads. So we use the Tcl TLS API.
169
Guido van Rossum00d93061998-05-28 23:06:38 +0000170*/
171
Guido van Rossum65d5b571998-12-21 19:32:43 +0000172static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000173
174#ifdef TCL_THREADS
175static Tcl_ThreadDataKey state_key;
176typedef PyThreadState *ThreadSpecificData;
177#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
178#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000179static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000180#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000181
182#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000183 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000184 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000185
186#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000187 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000188
Guido van Rossum62320c91998-06-15 04:36:09 +0000189#define ENTER_OVERLAP \
190 Py_END_ALLOW_THREADS
191
192#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000193 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000194
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000195#define ENTER_PYTHON \
196 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000197 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000198
199#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000200 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000201 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
202
203#define CHECK_TCL_APPARTMENT \
204 if (((TkappObject *)self)->threaded && \
205 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
206 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
207 return 0; \
208 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000209
210#else
211
212#define ENTER_TCL
213#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000214#define ENTER_OVERLAP
215#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000216#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000217#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000218#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000219
220#endif
221
Guido van Rossumec22c921996-02-25 04:50:29 +0000222#ifdef macintosh
223
224/*
225** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000226** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000227*/
228
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000229/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000230#define FREECAST (char *)
231
Guido van Rossumec22c921996-02-25 04:50:29 +0000232#include <Events.h> /* For EventRecord */
233
Fred Drake509d79a2000-07-08 04:04:38 +0000234typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
Guido van Rossum2834b972000-10-06 16:58:26 +0000235void Tcl_MacSetEventProc(TclMacConvertEventPtr procPtr);
236int TkMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000237
Jeremy Hylton938ace62002-07-17 16:30:39 +0000238static int PyMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000239
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000240#include <SIOUX.h>
241extern int SIOUXIsAppWindow(WindowPtr);
242
Guido van Rossumec22c921996-02-25 04:50:29 +0000243#endif /* macintosh */
244
Guido van Rossum97867b21996-08-08 19:09:53 +0000245#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000246#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000247#endif
248
Guido van Rossum18468821994-06-20 07:49:28 +0000249/**** Tkapp Object Declaration ****/
250
Jeremy Hylton938ace62002-07-17 16:30:39 +0000251static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000252
Guido van Rossum00d93061998-05-28 23:06:38 +0000253typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000254 PyObject_HEAD
255 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000256 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000257 int threaded; /* True if tcl_platform[threaded] */
258 Tcl_ThreadId thread_id;
259 int dispatching;
260 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000261 So we cache interesting types here. */
262 Tcl_ObjType *BooleanType;
263 Tcl_ObjType *ByteArrayType;
264 Tcl_ObjType *DoubleType;
265 Tcl_ObjType *IntType;
266 Tcl_ObjType *ListType;
267 Tcl_ObjType *ProcBodyType;
268 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000269} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000270
271#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000272#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000273#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000274
Guido van Rossum35d43371997-08-02 00:09:09 +0000275#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000276(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000277
Barry Warsawfa701a81997-01-16 00:15:11 +0000278
279
Guido van Rossum18468821994-06-20 07:49:28 +0000280/**** Error Handling ****/
281
282static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000283static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000284static int errorInCmd = 0;
285static PyObject *excInCmd;
286static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000287static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000288
Barry Warsawfa701a81997-01-16 00:15:11 +0000289
290
Guido van Rossum18468821994-06-20 07:49:28 +0000291static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000292Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000293{
Barry Warsawfa701a81997-01-16 00:15:11 +0000294 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
295 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000296}
297
Barry Warsawfa701a81997-01-16 00:15:11 +0000298
Barry Warsawfa701a81997-01-16 00:15:11 +0000299
Guido van Rossum18468821994-06-20 07:49:28 +0000300/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000301
302#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000303#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000304
Guido van Rossum00d93061998-05-28 23:06:38 +0000305/* Millisecond sleep() for Unix platforms. */
306
307static void
Fred Drake509d79a2000-07-08 04:04:38 +0000308Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000309{
310 /* XXX Too bad if you don't have select(). */
311 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000312 t.tv_sec = milli/1000;
313 t.tv_usec = (milli%1000) * 1000;
314 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
315}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000316#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000317#endif /* WITH_THREAD */
318
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000319/* Wait up to 1s for the mainloop to come up. */
320
321static int
322WaitForMainloop(TkappObject* self)
323{
324 int i;
325 for (i = 0; i < 10; i++) {
326 if (self->dispatching)
327 return 1;
328 Py_BEGIN_ALLOW_THREADS
329 Sleep(100);
330 Py_END_ALLOW_THREADS
331 }
332 if (self->dispatching)
333 return 1;
334 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
335 return 0;
336}
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000337
Guido van Rossum00d93061998-05-28 23:06:38 +0000338
Guido van Rossum18468821994-06-20 07:49:28 +0000339static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000340AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000341{
Guido van Rossum35d43371997-08-02 00:09:09 +0000342 if (PyString_Check(value))
343 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000344#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000345 else if (PyUnicode_Check(value)) {
346 PyObject *v = PyUnicode_AsUTF8String(value);
347 if (v == NULL)
348 return NULL;
349 if (PyList_Append(tmp, v) != 0) {
350 Py_DECREF(v);
351 return NULL;
352 }
353 Py_DECREF(v);
354 return PyString_AsString(v);
355 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000356#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000357 else {
358 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000359 if (v == NULL)
360 return NULL;
361 if (PyList_Append(tmp, v) != 0) {
362 Py_DECREF(v);
363 return NULL;
364 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000365 Py_DECREF(v);
366 return PyString_AsString(v);
367 }
Guido van Rossum18468821994-06-20 07:49:28 +0000368}
369
Barry Warsawfa701a81997-01-16 00:15:11 +0000370
371
Guido van Rossum18468821994-06-20 07:49:28 +0000372#define ARGSZ 64
373
374static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000375Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000376{
Barry Warsawfa701a81997-01-16 00:15:11 +0000377 PyObject *tmp = NULL;
378 char *argvStore[ARGSZ];
379 char **argv = NULL;
380 int fvStore[ARGSZ];
381 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000382 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000383 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000384
Barry Warsawfa701a81997-01-16 00:15:11 +0000385 if (!(tmp = PyList_New(0)))
386 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000387
Barry Warsawfa701a81997-01-16 00:15:11 +0000388 argv = argvStore;
389 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000390
Barry Warsawfa701a81997-01-16 00:15:11 +0000391 if (args == NULL)
392 argc = 0;
393
394 else if (!PyTuple_Check(args)) {
395 argc = 1;
396 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000397 if (!(argv[0] = AsString(args, tmp)))
398 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000399 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000400 else {
401 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000402
Barry Warsawfa701a81997-01-16 00:15:11 +0000403 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000404 argv = (char **)ckalloc(argc * sizeof(char *));
405 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000406 if (argv == NULL || fv == NULL) {
407 PyErr_NoMemory();
408 goto finally;
409 }
410 }
411
412 for (i = 0; i < argc; i++) {
413 PyObject *v = PyTuple_GetItem(args, i);
414 if (PyTuple_Check(v)) {
415 fv[i] = 1;
416 if (!(argv[i] = Merge(v)))
417 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000418 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000419 }
420 else if (v == Py_None) {
421 argc = i;
422 break;
423 }
424 else {
425 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000426 if (!(argv[i] = AsString(v, tmp)))
427 goto finally;
428 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000429 }
430 }
Guido van Rossum18468821994-06-20 07:49:28 +0000431 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000432 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000433 if (res == NULL)
434 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000435
Barry Warsawfa701a81997-01-16 00:15:11 +0000436 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000437 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000438 if (fv[i]) {
439 ckfree(argv[i]);
440 }
441 if (argv != argvStore)
442 ckfree(FREECAST argv);
443 if (fv != fvStore)
444 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000445
Barry Warsawfa701a81997-01-16 00:15:11 +0000446 Py_DECREF(tmp);
447 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000448}
449
Barry Warsawfa701a81997-01-16 00:15:11 +0000450
451
Guido van Rossum18468821994-06-20 07:49:28 +0000452static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000453Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000454{
Barry Warsawfa701a81997-01-16 00:15:11 +0000455 int argc;
456 char **argv;
457 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000458
Barry Warsawfa701a81997-01-16 00:15:11 +0000459 if (list == NULL) {
460 Py_INCREF(Py_None);
461 return Py_None;
462 }
Guido van Rossum18468821994-06-20 07:49:28 +0000463
Guido van Rossum00d93061998-05-28 23:06:38 +0000464 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000465 /* Not a list.
466 * Could be a quoted string containing funnies, e.g. {"}.
467 * Return the string itself.
468 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000469 return PyString_FromString(list);
470 }
Guido van Rossum18468821994-06-20 07:49:28 +0000471
Barry Warsawfa701a81997-01-16 00:15:11 +0000472 if (argc == 0)
473 v = PyString_FromString("");
474 else if (argc == 1)
475 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000476 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000477 int i;
478 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000479
Barry Warsawfa701a81997-01-16 00:15:11 +0000480 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000481 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000482 Py_DECREF(v);
483 v = NULL;
484 break;
485 }
486 PyTuple_SetItem(v, i, w);
487 }
488 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000489 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000490 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000491}
492
Martin v. Löwisffad6332002-11-26 09:28:05 +0000493/* In some cases, Tcl will still return strings that are supposed to be
494 lists. SplitObj walks through a nested tuple, finding string objects that
495 need to be split. */
496
497PyObject *
498SplitObj(PyObject *arg)
499{
500 if (PyTuple_Check(arg)) {
501 int i, size;
502 PyObject *elem, *newelem, *result;
503
504 size = PyTuple_Size(arg);
505 result = NULL;
506 /* Recursively invoke SplitObj for all tuple items.
507 If this does not return a new object, no action is
508 needed. */
509 for(i = 0; i < size; i++) {
510 elem = PyTuple_GetItem(arg, i);
511 newelem = SplitObj(elem);
512 if (!newelem) {
513 Py_XDECREF(result);
514 return NULL;
515 }
516 if (!result) {
517 int k;
518 if (newelem == elem) {
519 Py_DECREF(newelem);
520 continue;
521 }
522 result = PyTuple_New(size);
523 if (!result)
524 return NULL;
525 for(k = 0; k < i; k++) {
526 elem = PyTuple_GetItem(arg, k);
527 Py_INCREF(elem);
528 PyTuple_SetItem(result, k, elem);
529 }
530 }
531 PyTuple_SetItem(result, i, newelem);
532 }
533 if (result)
534 return result;
535 /* Fall through, returning arg. */
536 }
537 else if (PyString_Check(arg)) {
538 int argc;
539 char **argv;
540 char *list = PyString_AsString(arg);
541
542 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
543 Py_INCREF(arg);
544 return arg;
545 }
546 Tcl_Free(FREECAST argv);
547 if (argc > 1)
548 return Split(PyString_AsString(arg));
549 /* Fall through, returning arg. */
550 }
551 Py_INCREF(arg);
552 return arg;
553}
Barry Warsawfa701a81997-01-16 00:15:11 +0000554
555
Guido van Rossum18468821994-06-20 07:49:28 +0000556/**** Tkapp Object ****/
557
558#ifndef WITH_APPINIT
559int
Fred Drake509d79a2000-07-08 04:04:38 +0000560Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000561{
Barry Warsawfa701a81997-01-16 00:15:11 +0000562 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000563
Barry Warsawfa701a81997-01-16 00:15:11 +0000564 main = Tk_MainWindow(interp);
565 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000566 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000567 return TCL_ERROR;
568 }
569 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000570 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000571 return TCL_ERROR;
572 }
573 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000574}
575#endif /* !WITH_APPINIT */
576
Guido van Rossum18468821994-06-20 07:49:28 +0000577
Barry Warsawfa701a81997-01-16 00:15:11 +0000578
579
580/* Initialize the Tk application; see the `main' function in
581 * `tkMain.c'.
582 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000583
Thomas Wouters58d05102000-07-24 14:43:35 +0000584static void EnableEventHook(void); /* Forward */
585static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000586
Barry Warsawfa701a81997-01-16 00:15:11 +0000587static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000588Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000589 int interactive, int wantobjects)
Barry Warsawfa701a81997-01-16 00:15:11 +0000590{
591 TkappObject *v;
592 char *argv0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000593
Guido van Rossumb18618d2000-05-03 23:44:39 +0000594 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000595 if (v == NULL)
596 return NULL;
597
598 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000599 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000600 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
601 TCL_GLOBAL_ONLY) != NULL;
602 v->thread_id = Tcl_GetCurrentThread();
603 v->dispatching = 0;
604
605#ifndef TCL_THREADS
606 if (v->threaded) {
607 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
608 Py_DECREF(v);
609 return 0;
610 }
611#endif
612 if (v->threaded && tcl_lock) {
613 /* If Tcl is threaded, we don't need the lock. */
614 PyThread_free_lock(tcl_lock);
615 tcl_lock = NULL;
616 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000617
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000618 v->BooleanType = Tcl_GetObjType("boolean");
619 v->ByteArrayType = Tcl_GetObjType("bytearray");
620 v->DoubleType = Tcl_GetObjType("double");
621 v->IntType = Tcl_GetObjType("int");
622 v->ListType = Tcl_GetObjType("list");
623 v->ProcBodyType = Tcl_GetObjType("procbody");
624 v->StringType = Tcl_GetObjType("string");
625
Guido van Rossuma80649b2000-03-28 20:07:05 +0000626#if defined(macintosh)
627 /* This seems to be needed */
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000628 ClearMenuBar();
629 TkMacInitMenus(v->interp);
630#endif
Jack Jansencb852442001-12-09 23:15:56 +0000631
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000632 /* Delete the 'exit' command, which can screw things up */
633 Tcl_DeleteCommand(v->interp, "exit");
634
Barry Warsawfa701a81997-01-16 00:15:11 +0000635 if (screenName != NULL)
636 Tcl_SetVar2(v->interp, "env", "DISPLAY",
637 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000638
Barry Warsawfa701a81997-01-16 00:15:11 +0000639 if (interactive)
640 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
641 else
642 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000643
Barry Warsawfa701a81997-01-16 00:15:11 +0000644 /* This is used to get the application class for Tk 4.1 and up */
645 argv0 = (char*)ckalloc(strlen(className) + 1);
646 if (!argv0) {
647 PyErr_NoMemory();
648 Py_DECREF(v);
649 return NULL;
650 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000651
Barry Warsawfa701a81997-01-16 00:15:11 +0000652 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000653 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000654 argv0[0] = tolower(argv0[0]);
655 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
656 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000657
Barry Warsawfa701a81997-01-16 00:15:11 +0000658 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000659 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000660
Guido van Rossum7bf15641998-05-22 18:28:17 +0000661 EnableEventHook();
662
Barry Warsawfa701a81997-01-16 00:15:11 +0000663 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000664}
665
Barry Warsawfa701a81997-01-16 00:15:11 +0000666
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000667static void
668Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
669 Tcl_Condition *cond, Tcl_Mutex *mutex)
670{
671 Py_BEGIN_ALLOW_THREADS;
672 Tcl_MutexLock(mutex);
673 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
674 Tcl_ThreadAlert(self->thread_id);
675 Tcl_ConditionWait(cond, mutex, NULL);
676 Tcl_MutexUnlock(mutex);
677 Py_END_ALLOW_THREADS
678}
679
Barry Warsawfa701a81997-01-16 00:15:11 +0000680
Guido van Rossum18468821994-06-20 07:49:28 +0000681/** Tcl Eval **/
682
Martin v. Löwisffad6332002-11-26 09:28:05 +0000683typedef struct {
684 PyObject_HEAD
685 Tcl_Obj *value;
686} PyTclObject;
687
688staticforward PyTypeObject PyTclObject_Type;
689#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
690
691static PyObject *
692newPyTclObject(Tcl_Obj *arg)
693{
694 PyTclObject *self;
695 self = PyObject_New(PyTclObject, &PyTclObject_Type);
696 if (self == NULL)
697 return NULL;
698 Tcl_IncrRefCount(arg);
699 self->value = arg;
700 return (PyObject*)self;
701}
702
703static void
704PyTclObject_dealloc(PyTclObject *self)
705{
706 Tcl_DecrRefCount(self->value);
707 PyObject_Del(self);
708}
709
710static PyObject *
711PyTclObject_str(PyTclObject *self)
712{
713 return PyString_FromString(Tcl_GetString(self->value));
714}
715
716static PyObject *
717PyTclObject_repr(PyTclObject *self)
718{
719 char buf[50];
720 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
721 self->value->typePtr->name, (int)self->value);
722 return PyString_FromString(buf);
723}
724
725static PyObject*
726get_typename(PyTclObject* obj, void* ignored)
727{
728 return PyString_FromString(obj->value->typePtr->name);
729}
730
731static PyGetSetDef PyTclObject_getsetlist[] = {
732 {"typename", (getter)get_typename, NULL, "name of the Tcl type"},
733 {0},
734};
735
736statichere PyTypeObject PyTclObject_Type = {
737 PyObject_HEAD_INIT(NULL)
738 0, /*ob_size*/
739 "_tkinter.Tcl_Obj", /*tp_name*/
740 sizeof(PyTclObject), /*tp_basicsize*/
741 0, /*tp_itemsize*/
742 /* methods */
743 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
744 0, /*tp_print*/
745 0, /*tp_getattr*/
746 0, /*tp_setattr*/
747 0, /*tp_compare*/
748 (reprfunc)PyTclObject_repr, /*tp_repr*/
749 0, /*tp_as_number*/
750 0, /*tp_as_sequence*/
751 0, /*tp_as_mapping*/
752 0, /*tp_hash*/
753 0, /*tp_call*/
754 (reprfunc)PyTclObject_str, /*tp_str*/
755 PyObject_GenericGetAttr,/*tp_getattro*/
756 0, /*tp_setattro*/
757 0, /*tp_as_buffer*/
758 Py_TPFLAGS_DEFAULT, /*tp_flags*/
759 0, /*tp_doc*/
760 0, /*tp_traverse*/
761 0, /*tp_clear*/
762 0, /*tp_richcompare*/
763 0, /*tp_weaklistoffset*/
764 0, /*tp_iter*/
765 0, /*tp_iternext*/
766 0, /*tp_methods*/
767 0, /*tp_members*/
768 PyTclObject_getsetlist, /*tp_getset*/
769 0, /*tp_base*/
770 0, /*tp_dict*/
771 0, /*tp_descr_get*/
772 0, /*tp_descr_set*/
773 0, /*tp_dictoffset*/
774 0, /*tp_init*/
775 0, /*tp_alloc*/
776 0, /*tp_new*/
777 0, /*tp_free*/
778 0, /*tp_is_gc*/
779};
780
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000781static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000782AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000783{
784 Tcl_Obj *result;
785
786 if (PyString_Check(value))
787 return Tcl_NewStringObj(PyString_AS_STRING(value),
788 PyString_GET_SIZE(value));
789 else if (PyInt_Check(value))
790 return Tcl_NewLongObj(PyInt_AS_LONG(value));
791 else if (PyFloat_Check(value))
792 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
793 else if (PyTuple_Check(value)) {
794 Tcl_Obj **argv = (Tcl_Obj**)
795 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
796 int i;
797 if(!argv)
798 return 0;
799 for(i=0;i<PyTuple_Size(value);i++)
800 argv[i] = AsObj(PyTuple_GetItem(value,i));
801 result = Tcl_NewListObj(PyTuple_Size(value), argv);
802 ckfree(FREECAST argv);
803 return result;
804 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000805#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000806 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000807 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
808 int size = PyUnicode_GET_SIZE(value);
809 /* This #ifdef assumes that Tcl uses UCS-2.
810 See TCL_UTF_MAX test above. */
811#ifdef Py_UNICODE_WIDE
812 Tcl_UniChar *outbuf;
813 int i;
814 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
815 if (!outbuf) {
816 PyErr_NoMemory();
817 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000818 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000819 for (i = 0; i < size; i++) {
820 if (inbuf[i] >= 0x10000) {
821 /* Tcl doesn't do UTF-16, yet. */
822 PyErr_SetString(PyExc_ValueError,
823 "unsupported character");
824 ckfree(FREECAST outbuf);
825 return NULL;
826 }
827 outbuf[i] = inbuf[i];
828 }
829 result = Tcl_NewUnicodeObj(outbuf, size);
830 ckfree(FREECAST outbuf);
831 return result;
832#else
833 return Tcl_NewUnicodeObj(inbuf, size);
834#endif
835
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000836 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000837#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000838 else if(PyTclObject_Check(value)) {
839 Tcl_Obj *v = ((PyTclObject*)value)->value;
840 Tcl_IncrRefCount(v);
841 return v;
842 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000843 else {
844 PyObject *v = PyObject_Str(value);
845 if (!v)
846 return 0;
847 result = AsObj(v);
848 Py_DECREF(v);
849 return result;
850 }
851}
852
Martin v. Löwisffad6332002-11-26 09:28:05 +0000853static PyObject*
854FromObj(PyObject* tkapp, Tcl_Obj *value)
855{
856 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000857 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000858
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000859 if (value->typePtr == NULL) {
860 /* If the result contains any bytes with the top bit set,
861 it's UTF-8 and we should decode it to Unicode */
862#ifdef Py_USING_UNICODE
863 int i;
864 char *s = value->bytes;
865 int len = value->length;
866 for (i = 0; i < len; i++) {
867 if (value->bytes[i] & 0x80)
868 break;
869 }
870
871 if (i == value->length)
872 result = PyString_FromStringAndSize(s, len);
873 else {
874 /* Convert UTF-8 to Unicode string */
875 result = PyUnicode_DecodeUTF8(s, len, "strict");
876 if (result == NULL) {
877 PyErr_Clear();
878 result = PyString_FromStringAndSize(s, len);
879 }
880 }
881#else
882 res = PyString_FromStringAndSize(value->bytes, value->length);
883#endif
884 return result;
885 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000886
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000887 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000888 result = value->internalRep.longValue ? Py_True : Py_False;
889 Py_INCREF(result);
890 return result;
891 }
892
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000893 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000894 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000895 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000896 return PyString_FromStringAndSize(data, size);
897 }
898
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000899 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000900 return PyFloat_FromDouble(value->internalRep.doubleValue);
901 }
902
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000903 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000904 return PyInt_FromLong(value->internalRep.longValue);
905 }
906
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000907 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000908 int size;
909 int i, status;
910 PyObject *elem;
911 Tcl_Obj *tcl_elem;
912
913 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
914 if (status == TCL_ERROR)
915 return Tkinter_Error(tkapp);
916 result = PyTuple_New(size);
917 if (!result)
918 return NULL;
919 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000920 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +0000921 value, i, &tcl_elem);
922 if (status == TCL_ERROR) {
923 Py_DECREF(result);
924 return Tkinter_Error(tkapp);
925 }
926 elem = FromObj(tkapp, tcl_elem);
927 if (!elem) {
928 Py_DECREF(result);
929 return NULL;
930 }
931 PyTuple_SetItem(result, i, elem);
932 }
933 return result;
934 }
935
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000936 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000937 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000938 }
939
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000940 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000941#ifdef Py_USING_UNICODE
942#ifdef Py_UNICODE_WIDE
943 PyObject *result;
944 int size;
945 Tcl_UniChar *input;
946 Py_UNICODE *output;
947
948 size = Tcl_GetCharLength(value);
949 result = PyUnicode_FromUnicode(NULL, size);
950 if (!result)
951 return NULL;
952 input = Tcl_GetUnicode(value);
953 output = PyUnicode_AS_UNICODE(result);
954 while (size--)
955 *output++ = *input++;
956 return result;
957#else
958 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
959 Tcl_GetCharLength(value));
960#endif
961#else
962 int size;
963 char *c;
964 c = Tcl_GetStringFromObj(value, &size);
965 return PyString_FromStringAndSize(c, size);
966#endif
967 }
968
969 return newPyTclObject(value);
970}
971
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000972/* This mutex synchronizes inter-thread command calls. */
973
974TCL_DECLARE_MUTEX(call_mutex)
975
976typedef struct Tkapp_CallEvent {
977 Tcl_Event ev; /* Must be first */
978 TkappObject *self;
979 PyObject *args;
980 int flags;
981 PyObject **res;
982 PyObject **exc_type, **exc_value, **exc_tb;
983 Tcl_Condition done;
984} Tkapp_CallEvent;
985
986void
987Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +0000988{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000989 int i;
990 for (i = 0; i < objc; i++)
991 Tcl_DecrRefCount(objv[i]);
992 if (objv != objStore)
993 ckfree(FREECAST objv);
994}
Guido van Rossum18468821994-06-20 07:49:28 +0000995
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000996/* Convert Python objects to Tcl objects. This must happen in the
997 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +0000998
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000999static Tcl_Obj**
1000Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1001{
1002 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001003 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001004 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001005 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001006
Guido van Rossum212643f1998-04-29 16:22:14 +00001007 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001008 objv[0] = AsObj(args);
1009 if (objv[0] == 0)
1010 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001011 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001012 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001013 }
1014 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001015 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001016
Guido van Rossum632de272000-03-29 00:19:50 +00001017 if (objc > ARGSZ) {
1018 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1019 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001020 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001021 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001022 goto finally;
1023 }
1024 }
1025
Guido van Rossum632de272000-03-29 00:19:50 +00001026 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001027 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001028 if (v == Py_None) {
1029 objc = i;
1030 break;
1031 }
Guido van Rossum632de272000-03-29 00:19:50 +00001032 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001033 if (!objv[i]) {
1034 /* Reset objc, so it attempts to clear
1035 objects only up to i. */
1036 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001037 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001038 }
Guido van Rossum632de272000-03-29 00:19:50 +00001039 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001040 }
1041 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001042 *pobjc = objc;
1043 return objv;
1044finally:
1045 Tkapp_CallDeallocArgs(objv, objStore, objc);
1046 return NULL;
1047}
Guido van Rossum212643f1998-04-29 16:22:14 +00001048
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001049/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001050
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001051static PyObject*
1052Tkapp_CallResult(TkappObject *self)
1053{
1054 PyObject *res = NULL;
1055 if(self->wantobjects) {
1056 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001057 /* Not sure whether the IncrRef is necessary, but something
1058 may overwrite the interpreter result while we are
1059 converting it. */
1060 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001061 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001062 Tcl_DecrRefCount(value);
1063 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001064 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001065 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001066
Guido van Rossum990f5c62000-05-04 15:07:16 +00001067 /* If the result contains any bytes with the top bit set,
1068 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001069#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001070 while (*p != '\0') {
1071 if (*p & 0x80)
1072 break;
1073 p++;
1074 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001075
Guido van Rossum990f5c62000-05-04 15:07:16 +00001076 if (*p == '\0')
1077 res = PyString_FromStringAndSize(s, (int)(p-s));
1078 else {
1079 /* Convert UTF-8 to Unicode string */
1080 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001081 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1082 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001083 PyErr_Clear();
1084 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001085 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001086 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001087#else
1088 p = strchr(p, '\0');
1089 res = PyString_FromStringAndSize(s, (int)(p-s));
1090#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001091 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001092 return res;
1093}
Guido van Rossum632de272000-03-29 00:19:50 +00001094
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001095/* Tkapp_CallProc is the event procedure that is executed in the context of
1096 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1097 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001098
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001099static int
1100Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1101{
1102 Tcl_Obj *objStore[ARGSZ];
1103 Tcl_Obj **objv;
1104 int objc;
1105 int i;
1106 ENTER_PYTHON
1107 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1108 if (!objv) {
1109 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1110 *(e->res) = NULL;
1111 }
1112 LEAVE_PYTHON
1113 if (!objv)
1114 goto done;
1115 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1116 ENTER_PYTHON
1117 if (i == TCL_ERROR) {
1118 *(e->res) = NULL;
1119 *(e->exc_type) = NULL;
1120 *(e->exc_tb) = NULL;
1121 *(e->exc_value) = PyObject_CallFunction(
1122 Tkinter_TclError, "s",
1123 Tcl_GetStringResult(e->self->interp));
1124 }
1125 else {
1126 *(e->res) = Tkapp_CallResult(e->self);
1127 }
1128 LEAVE_PYTHON
1129 done:
1130 /* Wake up calling thread. */
1131 Tcl_MutexLock(&call_mutex);
1132 Tcl_ConditionNotify(&e->done);
1133 Tcl_MutexUnlock(&call_mutex);
1134 return 1;
1135}
1136
1137/* This is the main entry point for calling a Tcl command.
1138 It supports three cases, with regard to threading:
1139 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1140 the context of the calling thread.
1141 2. Tcl is threaded, caller of the command is in the interpreter thread:
1142 Execute the command in the calling thread. Since the Tcl lock will
1143 not be used, we can merge that with case 1.
1144 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1145 the interpreter thread. Allocation of Tcl objects needs to occur in the
1146 interpreter thread, so we ship the PyObject* args to the target thread,
1147 and perform processing there. */
1148
1149static PyObject *
1150Tkapp_Call(PyObject *_self, PyObject *args)
1151{
1152 Tcl_Obj *objStore[ARGSZ];
1153 Tcl_Obj **objv = NULL;
1154 int objc, i;
1155 PyObject *res = NULL;
1156 TkappObject *self = (TkappObject*)_self;
1157 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1158 int flags = TCL_EVAL_DIRECT;
1159
1160 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1161 /* We cannot call the command directly. Instead, we must
1162 marshal the parameters to the interpreter thread. */
1163 Tkapp_CallEvent *ev;
1164 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001165 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001166 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001167 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1168 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1169 ev->self = self;
1170 ev->args = args;
1171 ev->res = &res;
1172 ev->exc_type = &exc_type;
1173 ev->exc_value = &exc_value;
1174 ev->exc_tb = &exc_tb;
1175 ev->done = (Tcl_Condition)0;
1176
1177 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1178
1179 if (res == NULL) {
1180 if (exc_type)
1181 PyErr_Restore(exc_type, exc_value, exc_tb);
1182 else
1183 PyErr_SetObject(Tkinter_TclError, exc_value);
1184 }
1185 }
1186 else {
1187
1188 objv = Tkapp_CallArgs(args, objStore, &objc);
1189 if (!objv)
1190 return NULL;
1191
1192 ENTER_TCL
1193
1194 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1195
1196 ENTER_OVERLAP
1197
1198 if (i == TCL_ERROR)
1199 Tkinter_Error(_self);
1200 else
1201 res = Tkapp_CallResult(self);
1202
1203 LEAVE_OVERLAP_TCL
1204
1205 Tkapp_CallDeallocArgs(objv, objStore, objc);
1206 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001207 return res;
1208}
1209
1210
1211static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001212Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001213{
Guido van Rossum212643f1998-04-29 16:22:14 +00001214 /* Could do the same here as for Tkapp_Call(), but this is not used
1215 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1216 way for the user to do what all its Global* variants do (save and
1217 reset the scope pointer, call the local version, restore the saved
1218 scope pointer). */
1219
Guido van Rossum62320c91998-06-15 04:36:09 +00001220 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001221 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001222
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001223 CHECK_TCL_APPARTMENT;
1224
Guido van Rossum62320c91998-06-15 04:36:09 +00001225 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001226 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001227 int err;
1228 ENTER_TCL
1229 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001230 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001231 if (err == TCL_ERROR)
1232 res = Tkinter_Error(self);
1233 else
1234 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001235 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001236 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001237 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001238
1239 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001240}
1241
1242static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001243Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001244{
Barry Warsawfa701a81997-01-16 00:15:11 +00001245 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001246 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001247 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001248
Guido van Rossum43713e52000-02-29 13:59:29 +00001249 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001250 return NULL;
1251
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001252 CHECK_TCL_APPARTMENT;
1253
Guido van Rossum00d93061998-05-28 23:06:38 +00001254 ENTER_TCL
1255 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001256 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001257 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001258 res = Tkinter_Error(self);
1259 else
1260 res = PyString_FromString(Tkapp_Result(self));
1261 LEAVE_OVERLAP_TCL
1262 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001263}
1264
1265static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001266Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001267{
Barry Warsawfa701a81997-01-16 00:15:11 +00001268 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001269 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001270 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001271
Guido van Rossum43713e52000-02-29 13:59:29 +00001272 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001273 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001274
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001275 CHECK_TCL_APPARTMENT;
1276
Guido van Rossum00d93061998-05-28 23:06:38 +00001277 ENTER_TCL
1278 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001279 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001280 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001281 res = Tkinter_Error(self);
1282 else
1283 res = PyString_FromString(Tkapp_Result(self));
1284 LEAVE_OVERLAP_TCL
1285 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001286}
1287
1288static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001289Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001290{
Barry Warsawfa701a81997-01-16 00:15:11 +00001291 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001292 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001293 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001294
Guido van Rossum43713e52000-02-29 13:59:29 +00001295 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001296 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001297
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001298 CHECK_TCL_APPARTMENT;
1299
Guido van Rossum00d93061998-05-28 23:06:38 +00001300 ENTER_TCL
1301 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001302 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001303 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001304 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001305
Guido van Rossum62320c91998-06-15 04:36:09 +00001306 else
1307 res = PyString_FromString(Tkapp_Result(self));
1308 LEAVE_OVERLAP_TCL
1309 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001310}
1311
1312static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001313Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001314{
Barry Warsawfa701a81997-01-16 00:15:11 +00001315 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001316 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001317 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001318
Guido van Rossum35d43371997-08-02 00:09:09 +00001319 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001320 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001321
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001322 CHECK_TCL_APPARTMENT;
1323
Guido van Rossum00d93061998-05-28 23:06:38 +00001324 ENTER_TCL
1325 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001326 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001327 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001328 res = Tkinter_Error(self);
1329 else
1330 res = PyString_FromString(Tkapp_Result(self));
1331 LEAVE_OVERLAP_TCL
1332 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001333}
1334
1335static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001336Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001337{
Barry Warsawfa701a81997-01-16 00:15:11 +00001338 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001339
Guido van Rossum43713e52000-02-29 13:59:29 +00001340 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001341 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001342 CHECK_TCL_APPARTMENT;
1343
Guido van Rossum00d93061998-05-28 23:06:38 +00001344 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001345 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001346 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001347
Barry Warsawfa701a81997-01-16 00:15:11 +00001348 Py_INCREF(Py_None);
1349 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001350}
1351
Barry Warsawfa701a81997-01-16 00:15:11 +00001352
1353
Guido van Rossum18468821994-06-20 07:49:28 +00001354/** Tcl Variable **/
1355
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001356TCL_DECLARE_MUTEX(var_mutex)
1357
Martin v. Löwis5b177f12002-12-30 18:14:15 +00001358typedef CONST84_RETURN char* (*EventFunc1)(Tcl_Interp*, CONST char*, int);
1359typedef CONST84_RETURN char* (*EventFunc2)(Tcl_Interp*, CONST char*, CONST char*, int);
1360typedef CONST84_RETURN char* (*EventFunc3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001361typedef struct VarEvent {
1362 Tcl_Event ev; /* must be first */
1363 TkappObject *self;
1364 char* arg1;
1365 char* arg2;
1366 char* arg3;
1367 int flags;
1368 EventFunc1 func1;
1369 EventFunc2 func2;
1370 EventFunc3 func3;
1371 PyObject **res;
1372 PyObject **exc;
1373 Tcl_Condition cond;
1374 int coderesult;
1375} VarEvent;
1376
1377static const char*
1378var_perform(VarEvent *ev)
1379{
1380 if (!ev->arg2 && !ev->arg2)
1381 return ev->func1(ev->self->interp, ev->arg1, ev->flags);
1382 if (!ev->arg3)
1383 return ev->func2(ev->self->interp, ev->arg1,
1384 ev->arg2, ev->flags);
1385 return ev->func3(ev->self->interp, ev->arg1, ev->arg2,
1386 ev->arg3, ev->flags);
1387}
1388
1389static void
1390var_fill_result(VarEvent *ev, const char* res)
1391{
1392 if (ev->coderesult) {
1393 if ((int)res != TCL_ERROR) {
1394 Py_INCREF(Py_None);
1395 *(ev->res) = Py_None;
1396 return;
1397 }
1398 }
1399 else if (res) {
1400 *(ev->res) = PyString_FromString(res);
1401 return;
1402 }
1403
1404 *(ev->res) = NULL;
1405 *(ev->exc) = PyObject_CallFunction(
1406 Tkinter_TclError, "s",
1407 Tcl_GetStringResult(ev->self->interp));
1408
1409}
1410
1411static int
1412var_proc(VarEvent* ev, int flags)
1413{
1414 const char *result = var_perform(ev);
1415 ENTER_PYTHON
1416 var_fill_result(ev, result);
1417 Tcl_MutexLock(&var_mutex);
1418 Tcl_ConditionNotify(&ev->cond);
1419 Tcl_MutexUnlock(&var_mutex);
1420 LEAVE_PYTHON
1421 return 1;
1422}
1423
1424static PyObject*
1425var_invoke(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
1426 EventFunc1 func1, EventFunc2 func2, EventFunc3 func3,
1427 int coderesult)
1428{
1429 VarEvent _ev;
1430 TkappObject *self = (TkappObject*)_self;
1431 VarEvent *ev = self->threaded ?
1432 (VarEvent*)ckalloc(sizeof(VarEvent)) : &_ev;
1433 PyObject *res, *exc;
1434
1435 ev->self = self;
1436 ev->arg1 = arg1;
1437 ev->arg2 = arg2;
1438 ev->arg3 = arg3;
1439 ev->flags = flags;
1440 ev->func1 = func1;
1441 ev->func2 = func2;
1442 ev->func3 = func3;
1443 ev->coderesult = coderesult;
1444 ev->res = &res;
1445 ev->exc = &exc;
1446 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1447 /* The current thread is not the interpreter thread. Marshal
1448 the call to the interpreter thread, then wait for
1449 completion. */
1450
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001451 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001452 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001453 ev->cond = NULL;
1454 ev->ev.proc = (Tcl_EventProc*)var_proc;
1455 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1456 }
1457 else {
1458 /* Tcl is not threaded, or this is the interpreter thread. To
1459 perform the call, we must hold the TCL lock. To receive the
1460 results, we must also hold the Python lock. */
1461 const char *result;
1462 ENTER_TCL
1463 result = var_perform(ev);
1464 ENTER_OVERLAP
1465 var_fill_result(ev, result);
1466 LEAVE_OVERLAP_TCL
1467 }
1468 if (!res) {
1469 PyErr_SetObject(Tkinter_TclError, exc);
1470 return NULL;
1471 }
1472 return res;
1473}
1474
1475static PyObject*
1476var_invoke2(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
Martin v. Löwis5b177f12002-12-30 18:14:15 +00001477 int (*func1)(Tcl_Interp*, CONST char*, int),
1478 int (*func2)(Tcl_Interp*, CONST char*, CONST char*, int),
1479 int (*func3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001480{
1481 return var_invoke(_self, arg1, arg2, arg3, flags,
1482 (EventFunc1)func1, (EventFunc2)func2,
1483 (EventFunc3)func3, 1);
1484}
1485
Guido van Rossum18468821994-06-20 07:49:28 +00001486static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001487SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001488{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001489 char *name1, *name2, *s;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001490 PyObject *res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001491 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +00001492 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +00001493
Guido van Rossum62320c91998-06-15 04:36:09 +00001494 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +00001495 if (!tmp)
1496 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001497
Guido van Rossum43713e52000-02-29 13:59:29 +00001498 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001499 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +00001500 s = AsString(newValue, tmp);
Guido van Rossum2834b972000-10-06 16:58:26 +00001501 if (s == NULL)
1502 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001503 res = var_invoke(self, name1, s, NULL, flags,
1504 NULL, Tcl_SetVar, NULL, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001505 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001506 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001507 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001508 if (PyArg_ParseTuple(args, "ssO:setvar",
1509 &name1, &name2, &newValue)) {
1510 s = AsString(newValue, tmp);
1511 if (s == NULL)
1512 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001513 res = var_invoke(self, name1, name2, s, flags,
1514 NULL, NULL, Tcl_SetVar2, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001515 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001516 else {
Guido van Rossum00d93061998-05-28 23:06:38 +00001517 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +00001518 return NULL;
1519 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001520 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001521 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +00001522
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001523 if (!res)
1524 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001525
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001526 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001527 Py_INCREF(Py_None);
1528 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001529}
1530
1531static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001532Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001533{
Barry Warsawfa701a81997-01-16 00:15:11 +00001534 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001535}
1536
1537static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001538Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001539{
Barry Warsawfa701a81997-01-16 00:15:11 +00001540 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001541}
1542
Barry Warsawfa701a81997-01-16 00:15:11 +00001543
1544
Guido van Rossum18468821994-06-20 07:49:28 +00001545static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001546GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001547{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001548 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001549 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001550
Guido van Rossum43713e52000-02-29 13:59:29 +00001551 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001552 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001553
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001554 res = var_invoke(self, name1, name2, NULL, flags,
1555 Tcl_GetVar, Tcl_GetVar2, NULL, 0);
Guido van Rossum62320c91998-06-15 04:36:09 +00001556 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001557}
1558
1559static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001560Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001561{
Barry Warsawfa701a81997-01-16 00:15:11 +00001562 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001563}
1564
1565static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001566Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001567{
Barry Warsawfa701a81997-01-16 00:15:11 +00001568 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001569}
1570
Barry Warsawfa701a81997-01-16 00:15:11 +00001571
1572
Guido van Rossum18468821994-06-20 07:49:28 +00001573static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001574UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001575{
Guido van Rossum35d43371997-08-02 00:09:09 +00001576 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001577 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001578
Guido van Rossum43713e52000-02-29 13:59:29 +00001579 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001580 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001581
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001582 res = var_invoke2(self, name1, name2, NULL, flags,
1583 Tcl_UnsetVar, Tcl_UnsetVar2, NULL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001584 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001585}
1586
1587static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001588Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001589{
Barry Warsawfa701a81997-01-16 00:15:11 +00001590 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001591}
1592
1593static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001594Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001595{
Barry Warsawfa701a81997-01-16 00:15:11 +00001596 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001597}
1598
Barry Warsawfa701a81997-01-16 00:15:11 +00001599
1600
Guido van Rossum18468821994-06-20 07:49:28 +00001601/** Tcl to Python **/
1602
1603static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001604Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001605{
Barry Warsawfa701a81997-01-16 00:15:11 +00001606 char *s;
1607 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001608
Martin v. Löwisffad6332002-11-26 09:28:05 +00001609 if (PyTuple_Size(args) == 1) {
1610 PyObject* o = PyTuple_GetItem(args, 0);
1611 if (PyInt_Check(o)) {
1612 Py_INCREF(o);
1613 return o;
1614 }
1615 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001616 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001617 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001618 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001619 return Tkinter_Error(self);
1620 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001621}
1622
1623static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001624Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001625{
Barry Warsawfa701a81997-01-16 00:15:11 +00001626 char *s;
1627 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001628
Martin v. Löwisffad6332002-11-26 09:28:05 +00001629 if (PyTuple_Size(args) == 1) {
1630 PyObject *o = PyTuple_GetItem(args, 0);
1631 if (PyFloat_Check(o)) {
1632 Py_INCREF(o);
1633 return o;
1634 }
1635 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001636 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001637 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001638 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001639 return Tkinter_Error(self);
1640 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001641}
1642
1643static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001644Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001645{
Barry Warsawfa701a81997-01-16 00:15:11 +00001646 char *s;
1647 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001648
Martin v. Löwisffad6332002-11-26 09:28:05 +00001649 if (PyTuple_Size(args) == 1) {
1650 PyObject *o = PyTuple_GetItem(args, 0);
1651 if (PyInt_Check(o)) {
1652 Py_INCREF(o);
1653 return o;
1654 }
1655 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001656 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001657 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001658 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1659 return Tkinter_Error(self);
Barry Warsawfa701a81997-01-16 00:15:11 +00001660 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001661}
1662
1663static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001664Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001665{
Barry Warsawfa701a81997-01-16 00:15:11 +00001666 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001667 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001668 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001669
Guido van Rossum43713e52000-02-29 13:59:29 +00001670 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001671 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001672
1673 CHECK_TCL_APPARTMENT;
1674
Guido van Rossum00d93061998-05-28 23:06:38 +00001675 ENTER_TCL
1676 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001677 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001678 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001679 res = Tkinter_Error(self);
1680 else
1681 res = Py_BuildValue("s", Tkapp_Result(self));
1682 LEAVE_OVERLAP_TCL
1683 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001684}
1685
1686static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001687Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001688{
Barry Warsawfa701a81997-01-16 00:15:11 +00001689 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001690 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001691 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001692 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001693
Guido van Rossum43713e52000-02-29 13:59:29 +00001694 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001695 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001696
1697 CHECK_TCL_APPARTMENT;
1698
Guido van Rossum00d93061998-05-28 23:06:38 +00001699 ENTER_TCL
1700 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001701 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001702 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001703 res = Tkinter_Error(self);
1704 else
1705 res = Py_BuildValue("l", v);
1706 LEAVE_OVERLAP_TCL
1707 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001708}
1709
1710static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001711Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001712{
Barry Warsawfa701a81997-01-16 00:15:11 +00001713 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001714 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001715 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001716 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001717
Guido van Rossum43713e52000-02-29 13:59:29 +00001718 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001719 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001720 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001721 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001722 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001723 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001724 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001725 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001726 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001727 res = Tkinter_Error(self);
1728 else
1729 res = Py_BuildValue("d", v);
1730 LEAVE_OVERLAP_TCL
1731 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001732}
1733
1734static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001735Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001736{
Barry Warsawfa701a81997-01-16 00:15:11 +00001737 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001738 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001739 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001740 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001741
Guido van Rossum43713e52000-02-29 13:59:29 +00001742 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001743 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001744 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001745 ENTER_TCL
1746 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001747 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001748 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001749 res = Tkinter_Error(self);
1750 else
1751 res = Py_BuildValue("i", v);
1752 LEAVE_OVERLAP_TCL
1753 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001754}
1755
Barry Warsawfa701a81997-01-16 00:15:11 +00001756
1757
Guido van Rossum18468821994-06-20 07:49:28 +00001758static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001759Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001760{
Barry Warsawfa701a81997-01-16 00:15:11 +00001761 char *list;
1762 int argc;
1763 char **argv;
1764 PyObject *v;
1765 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001766
Martin v. Löwisffad6332002-11-26 09:28:05 +00001767 if (PyTuple_Size(args) == 1) {
1768 v = PyTuple_GetItem(args, 0);
1769 if (PyTuple_Check(v)) {
1770 Py_INCREF(v);
1771 return v;
1772 }
1773 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001774 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001775 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001776
Barry Warsawfa701a81997-01-16 00:15:11 +00001777 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1778 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001779
Barry Warsawfa701a81997-01-16 00:15:11 +00001780 if (!(v = PyTuple_New(argc)))
1781 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001782
Barry Warsawfa701a81997-01-16 00:15:11 +00001783 for (i = 0; i < argc; i++) {
1784 PyObject *s = PyString_FromString(argv[i]);
1785 if (!s || PyTuple_SetItem(v, i, s)) {
1786 Py_DECREF(v);
1787 v = NULL;
1788 goto finally;
1789 }
1790 }
Guido van Rossum18468821994-06-20 07:49:28 +00001791
Barry Warsawfa701a81997-01-16 00:15:11 +00001792 finally:
1793 ckfree(FREECAST argv);
1794 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001795}
1796
1797static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001798Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001799{
Barry Warsawfa701a81997-01-16 00:15:11 +00001800 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001801
Martin v. Löwisffad6332002-11-26 09:28:05 +00001802 if (PyTuple_Size(args) == 1) {
1803 PyObject* o = PyTuple_GetItem(args, 0);
1804 if (PyTuple_Check(o)) {
1805 o = SplitObj(o);
1806 return o;
1807 }
1808 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001809 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001810 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001811 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001812}
1813
1814static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001815Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001816{
Barry Warsawfa701a81997-01-16 00:15:11 +00001817 char *s = Merge(args);
1818 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001819
Barry Warsawfa701a81997-01-16 00:15:11 +00001820 if (s) {
1821 res = PyString_FromString(s);
1822 ckfree(s);
1823 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001824
1825 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001826}
1827
Barry Warsawfa701a81997-01-16 00:15:11 +00001828
1829
Guido van Rossum18468821994-06-20 07:49:28 +00001830/** Tcl Command **/
1831
Guido van Rossum00d93061998-05-28 23:06:38 +00001832/* Client data struct */
1833typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001834 PyObject *self;
1835 PyObject *func;
1836} PythonCmd_ClientData;
1837
1838static int
Fred Drake509d79a2000-07-08 04:04:38 +00001839PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001840{
1841 errorInCmd = 1;
1842 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1843 LEAVE_PYTHON
1844 return TCL_ERROR;
1845}
1846
Guido van Rossum18468821994-06-20 07:49:28 +00001847/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001848 * function or method.
1849 */
Guido van Rossum18468821994-06-20 07:49:28 +00001850static int
Fred Drake509d79a2000-07-08 04:04:38 +00001851PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001852{
Guido van Rossum00d93061998-05-28 23:06:38 +00001853 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001854 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001855 int i, rv;
1856 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001857
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001858 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001859
Barry Warsawfa701a81997-01-16 00:15:11 +00001860 /* TBD: no error checking here since we know, via the
1861 * Tkapp_CreateCommand() that the client data is a two-tuple
1862 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001863 self = data->self;
1864 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001865
Barry Warsawfa701a81997-01-16 00:15:11 +00001866 /* Create argument list (argv1, ..., argvN) */
1867 if (!(arg = PyTuple_New(argc - 1)))
1868 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001869
Barry Warsawfa701a81997-01-16 00:15:11 +00001870 for (i = 0; i < (argc - 1); i++) {
1871 PyObject *s = PyString_FromString(argv[i + 1]);
1872 if (!s || PyTuple_SetItem(arg, i, s)) {
1873 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001874 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001875 }
1876 }
1877 res = PyEval_CallObject(func, arg);
1878 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001879
Barry Warsawfa701a81997-01-16 00:15:11 +00001880 if (res == NULL)
1881 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001882
Barry Warsawfa701a81997-01-16 00:15:11 +00001883 if (!(tmp = PyList_New(0))) {
1884 Py_DECREF(res);
1885 return PythonCmd_Error(interp);
1886 }
1887
Guido van Rossum2834b972000-10-06 16:58:26 +00001888 s = AsString(res, tmp);
1889 if (s == NULL) {
1890 rv = PythonCmd_Error(interp);
1891 }
1892 else {
1893 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1894 rv = TCL_OK;
1895 }
1896
Barry Warsawfa701a81997-01-16 00:15:11 +00001897 Py_DECREF(res);
1898 Py_DECREF(tmp);
1899
Guido van Rossum00d93061998-05-28 23:06:38 +00001900 LEAVE_PYTHON
1901
Guido van Rossum2834b972000-10-06 16:58:26 +00001902 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001903}
1904
1905static void
Fred Drake509d79a2000-07-08 04:04:38 +00001906PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001907{
Guido van Rossum00d93061998-05-28 23:06:38 +00001908 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1909
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001910 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001911 Py_XDECREF(data->self);
1912 Py_XDECREF(data->func);
1913 PyMem_DEL(data);
1914 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001915}
1916
Barry Warsawfa701a81997-01-16 00:15:11 +00001917
1918
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001919
1920TCL_DECLARE_MUTEX(command_mutex)
1921
1922typedef struct CommandEvent{
1923 Tcl_Event ev;
1924 Tcl_Interp* interp;
1925 char *name;
1926 int create;
1927 int *status;
1928 ClientData *data;
1929 Tcl_Condition done;
1930} CommandEvent;
1931
1932static int
1933Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001934{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001935 if (ev->create)
1936 *ev->status = Tcl_CreateCommand(
1937 ev->interp, ev->name, PythonCmd,
1938 ev->data, PythonCmdDelete) == NULL;
1939 else
1940 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1941 Tcl_MutexLock(&command_mutex);
1942 Tcl_ConditionNotify(&ev->done);
1943 Tcl_MutexUnlock(&command_mutex);
1944 return 1;
1945}
1946
1947static PyObject *
1948Tkapp_CreateCommand(PyObject *_self, PyObject *args)
1949{
1950 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001951 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001952 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00001953 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001954 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001955
Guido van Rossum43713e52000-02-29 13:59:29 +00001956 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00001957 return NULL;
1958 if (!PyCallable_Check(func)) {
1959 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00001960 return NULL;
1961 }
Guido van Rossum18468821994-06-20 07:49:28 +00001962
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001963 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001964 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001965 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001966
Guido van Rossum00d93061998-05-28 23:06:38 +00001967 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00001968 if (!data)
1969 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001970 Py_XINCREF(self);
1971 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001972 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001973 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001974
1975 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1976 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
1977 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
1978 ev->interp = self->interp;
1979 ev->create = 1;
1980 ev->name = cmdName;
1981 ev->data = (ClientData)data;
1982 ev->status = &err;
1983 ev->done = NULL;
1984 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
1985 }
1986 else {
1987 ENTER_TCL
1988 err = Tcl_CreateCommand(
1989 Tkapp_Interp(self), cmdName, PythonCmd,
1990 (ClientData)data, PythonCmdDelete) == NULL;
1991 LEAVE_TCL
1992 }
1993 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001994 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00001995 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00001996 return NULL;
1997 }
Guido van Rossum18468821994-06-20 07:49:28 +00001998
Barry Warsawfa701a81997-01-16 00:15:11 +00001999 Py_INCREF(Py_None);
2000 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002001}
2002
Barry Warsawfa701a81997-01-16 00:15:11 +00002003
2004
Guido van Rossum18468821994-06-20 07:49:28 +00002005static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002006Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002007{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002008 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002009 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002010 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002011
Guido van Rossum43713e52000-02-29 13:59:29 +00002012 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002013 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002014 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2015 CommandEvent *ev;
2016 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2017 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2018 ev->interp = self->interp;
2019 ev->create = 0;
2020 ev->name = cmdName;
2021 ev->status = &err;
2022 ev->done = NULL;
2023 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2024 &command_mutex);
2025 }
2026 else {
2027 ENTER_TCL
2028 err = Tcl_DeleteCommand(self->interp, cmdName);
2029 LEAVE_TCL
2030 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002031 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002032 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2033 return NULL;
2034 }
2035 Py_INCREF(Py_None);
2036 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002037}
2038
Barry Warsawfa701a81997-01-16 00:15:11 +00002039
2040
Guido van Rossum00d93061998-05-28 23:06:38 +00002041#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002042/** File Handler **/
2043
Guido van Rossum00d93061998-05-28 23:06:38 +00002044typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002045 PyObject *func;
2046 PyObject *file;
2047 int id;
2048 struct _fhcdata *next;
2049} FileHandler_ClientData;
2050
2051static FileHandler_ClientData *HeadFHCD;
2052
2053static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002054NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002055{
2056 FileHandler_ClientData *p;
2057 p = PyMem_NEW(FileHandler_ClientData, 1);
2058 if (p != NULL) {
2059 Py_XINCREF(func);
2060 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002061 p->func = func;
2062 p->file = file;
2063 p->id = id;
2064 p->next = HeadFHCD;
2065 HeadFHCD = p;
2066 }
2067 return p;
2068}
2069
2070static void
Fred Drake509d79a2000-07-08 04:04:38 +00002071DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002072{
2073 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002074
2075 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002076 while ((p = *pp) != NULL) {
2077 if (p->id == id) {
2078 *pp = p->next;
2079 Py_XDECREF(p->func);
2080 Py_XDECREF(p->file);
2081 PyMem_DEL(p);
2082 }
2083 else
2084 pp = &p->next;
2085 }
2086}
2087
Guido van Rossuma597dde1995-01-10 20:56:29 +00002088static void
Fred Drake509d79a2000-07-08 04:04:38 +00002089FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002090{
Guido van Rossum00d93061998-05-28 23:06:38 +00002091 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002092 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002093
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002094 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002095 func = data->func;
2096 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002097
Barry Warsawfa701a81997-01-16 00:15:11 +00002098 arg = Py_BuildValue("(Oi)", file, (long) mask);
2099 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002100 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002101
2102 if (res == NULL) {
2103 errorInCmd = 1;
2104 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2105 }
2106 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002107 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002108}
2109
Guido van Rossum18468821994-06-20 07:49:28 +00002110static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002111Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2112 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002113{
Guido van Rossum00d93061998-05-28 23:06:38 +00002114 FileHandler_ClientData *data;
2115 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002116 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002117
Guido van Rossum2834b972000-10-06 16:58:26 +00002118 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2119 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002120 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002121 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002122 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002123 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002124 return NULL;
2125 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002126 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002127 return NULL;
2128 }
2129
Guido van Rossuma80649b2000-03-28 20:07:05 +00002130 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002131 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002132 return NULL;
2133
Barry Warsawfa701a81997-01-16 00:15:11 +00002134 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002135 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002136 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002137 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002138 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002139 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002140}
2141
2142static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002143Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002144{
Barry Warsawfa701a81997-01-16 00:15:11 +00002145 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002146 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002147
Guido van Rossum43713e52000-02-29 13:59:29 +00002148 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002149 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002150 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002151 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002152 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002153 return NULL;
2154
Guido van Rossuma80649b2000-03-28 20:07:05 +00002155 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002156
Barry Warsawfa701a81997-01-16 00:15:11 +00002157 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002158 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002159 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002160 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002161 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002162 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002163}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002164#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002165
Barry Warsawfa701a81997-01-16 00:15:11 +00002166
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002167/**** Tktt Object (timer token) ****/
2168
Jeremy Hylton938ace62002-07-17 16:30:39 +00002169static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002170
Guido van Rossum00d93061998-05-28 23:06:38 +00002171typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002172 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002173 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002174 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002175} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002176
2177static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002178Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002179{
Barry Warsawfa701a81997-01-16 00:15:11 +00002180 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002181 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002182
Guido van Rossum43713e52000-02-29 13:59:29 +00002183 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002184 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002185 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002186 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002187 v->token = NULL;
2188 }
2189 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002190 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002191 Py_DECREF(func);
2192 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002193 }
2194 Py_INCREF(Py_None);
2195 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002196}
2197
2198static PyMethodDef Tktt_methods[] =
2199{
Neal Norwitzb0493252002-03-31 14:44:22 +00002200 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002201 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002202};
2203
2204static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002205Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002206{
Barry Warsawfa701a81997-01-16 00:15:11 +00002207 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002208
Guido van Rossumb18618d2000-05-03 23:44:39 +00002209 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002210 if (v == NULL)
2211 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002212
Guido van Rossum00d93061998-05-28 23:06:38 +00002213 Py_INCREF(func);
2214 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002215 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002216
2217 /* Extra reference, deleted when called or when handler is deleted */
2218 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002219 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002220}
2221
2222static void
Fred Drake509d79a2000-07-08 04:04:38 +00002223Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002224{
Guido van Rossum00d93061998-05-28 23:06:38 +00002225 TkttObject *v = (TkttObject *)self;
2226 PyObject *func = v->func;
2227
2228 Py_XDECREF(func);
2229
Guido van Rossumb18618d2000-05-03 23:44:39 +00002230 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002231}
2232
Guido van Rossum597ac201998-05-12 14:36:19 +00002233static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002234Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002235{
Barry Warsawfa701a81997-01-16 00:15:11 +00002236 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002237 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002238
Tim Peters885d4572001-11-28 20:27:42 +00002239 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002240 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002241 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002242}
2243
2244static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002245Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002246{
Barry Warsawfa701a81997-01-16 00:15:11 +00002247 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002248}
2249
2250static PyTypeObject Tktt_Type =
2251{
Guido van Rossum35d43371997-08-02 00:09:09 +00002252 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002253 0, /*ob_size */
2254 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002255 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002256 0, /*tp_itemsize */
2257 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002258 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002259 Tktt_GetAttr, /*tp_getattr */
2260 0, /*tp_setattr */
2261 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002262 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002263 0, /*tp_as_number */
2264 0, /*tp_as_sequence */
2265 0, /*tp_as_mapping */
2266 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002267};
2268
Barry Warsawfa701a81997-01-16 00:15:11 +00002269
2270
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002271/** Timer Handler **/
2272
2273static void
Fred Drake509d79a2000-07-08 04:04:38 +00002274TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002275{
Guido van Rossum00d93061998-05-28 23:06:38 +00002276 TkttObject *v = (TkttObject *)clientData;
2277 PyObject *func = v->func;
2278 PyObject *res;
2279
2280 if (func == NULL)
2281 return;
2282
2283 v->func = NULL;
2284
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002285 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002286
2287 res = PyEval_CallObject(func, NULL);
2288 Py_DECREF(func);
2289 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002290
Barry Warsawfa701a81997-01-16 00:15:11 +00002291 if (res == NULL) {
2292 errorInCmd = 1;
2293 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2294 }
2295 else
2296 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002297
2298 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002299}
2300
2301static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002302Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002303{
Barry Warsawfa701a81997-01-16 00:15:11 +00002304 int milliseconds;
2305 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002306 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002307
Guido van Rossum2834b972000-10-06 16:58:26 +00002308 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2309 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002310 return NULL;
2311 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002312 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002313 return NULL;
2314 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002315 v = Tktt_New(func);
2316 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2317 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002318
Guido van Rossum00d93061998-05-28 23:06:38 +00002319 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002320}
2321
Barry Warsawfa701a81997-01-16 00:15:11 +00002322
Guido van Rossum18468821994-06-20 07:49:28 +00002323/** Event Loop **/
2324
Guido van Rossum18468821994-06-20 07:49:28 +00002325static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002326Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002327{
Barry Warsawfa701a81997-01-16 00:15:11 +00002328 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002329 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002330#ifdef WITH_THREAD
2331 PyThreadState *tstate = PyThreadState_Get();
2332#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002333
Guido van Rossum43713e52000-02-29 13:59:29 +00002334 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002335 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002336
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002337 CHECK_TCL_APPARTMENT;
2338
Barry Warsawfa701a81997-01-16 00:15:11 +00002339 quitMainLoop = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002340 self->dispatching = 1;
Barry Warsawfa701a81997-01-16 00:15:11 +00002341 while (Tk_GetNumMainWindows() > threshold &&
2342 !quitMainLoop &&
2343 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002344 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002345 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002346
2347#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002348 if (self->threaded) {
2349 /* Allow other Python threads to run. */
2350 ENTER_TCL
2351 result = Tcl_DoOneEvent(0);
2352 LEAVE_TCL
2353 }
2354 else {
2355 Py_BEGIN_ALLOW_THREADS
2356 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2357 tcl_tstate = tstate;
2358 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2359 tcl_tstate = NULL;
2360 if(tcl_lock)PyThread_release_lock(tcl_lock);
2361 if (result == 0)
2362 Sleep(20);
2363 Py_END_ALLOW_THREADS
2364 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002365#else
2366 result = Tcl_DoOneEvent(0);
2367#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002368
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002369 if (PyErr_CheckSignals() != 0) {
2370 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002371 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002372 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002373 if (result < 0)
2374 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002375 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002376 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002377 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002378
Barry Warsawfa701a81997-01-16 00:15:11 +00002379 if (errorInCmd) {
2380 errorInCmd = 0;
2381 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2382 excInCmd = valInCmd = trbInCmd = NULL;
2383 return NULL;
2384 }
2385 Py_INCREF(Py_None);
2386 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002387}
2388
2389static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002390Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002391{
Guido van Rossum35d43371997-08-02 00:09:09 +00002392 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002393 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002394
Guido van Rossum43713e52000-02-29 13:59:29 +00002395 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002396 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002397 CHECK_TCL_APPARTMENT;
Barry Warsawfa701a81997-01-16 00:15:11 +00002398
Guido van Rossum00d93061998-05-28 23:06:38 +00002399 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002400 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002401 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002402 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002403}
2404
2405static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002406Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002407{
2408
Guido van Rossum43713e52000-02-29 13:59:29 +00002409 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002410 return NULL;
2411
2412 quitMainLoop = 1;
2413 Py_INCREF(Py_None);
2414 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002415}
2416
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002417static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002418Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002419{
2420
Guido van Rossum43713e52000-02-29 13:59:29 +00002421 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002422 return NULL;
2423
2424 return PyInt_FromLong((long)Tkapp_Interp(self));
2425}
2426
Barry Warsawfa701a81997-01-16 00:15:11 +00002427
Martin v. Löwisffad6332002-11-26 09:28:05 +00002428static PyObject *
2429Tkapp_WantObjects(PyObject *self, PyObject *args)
2430{
2431
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002432 int wantobjects;
2433 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002434 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002435 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002436
2437 Py_INCREF(Py_None);
2438 return Py_None;
2439}
2440
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002441static PyObject *
2442Tkapp_WillDispatch(PyObject *self, PyObject *args)
2443{
2444
2445 ((TkappObject*)self)->dispatching = 1;
2446
2447 Py_INCREF(Py_None);
2448 return Py_None;
2449}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002450
Barry Warsawfa701a81997-01-16 00:15:11 +00002451
Guido van Rossum18468821994-06-20 07:49:28 +00002452/**** Tkapp Method List ****/
2453
2454static PyMethodDef Tkapp_methods[] =
2455{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002456 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002457 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002458 {"call", Tkapp_Call, METH_OLDARGS},
2459 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2460 {"eval", Tkapp_Eval, METH_VARARGS},
2461 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2462 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2463 {"record", Tkapp_Record, METH_VARARGS},
2464 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2465 {"setvar", Tkapp_SetVar, METH_VARARGS},
2466 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2467 {"getvar", Tkapp_GetVar, METH_VARARGS},
2468 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2469 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2470 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2471 {"getint", Tkapp_GetInt, METH_VARARGS},
2472 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2473 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2474 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2475 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2476 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2477 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2478 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2479 {"split", Tkapp_Split, METH_VARARGS},
2480 {"merge", Tkapp_Merge, METH_OLDARGS},
2481 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2482 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002483#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002484 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2485 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002486#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002487 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2488 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2489 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2490 {"quit", Tkapp_Quit, METH_VARARGS},
2491 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002492 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002493};
2494
Barry Warsawfa701a81997-01-16 00:15:11 +00002495
2496
Guido van Rossum18468821994-06-20 07:49:28 +00002497/**** Tkapp Type Methods ****/
2498
2499static void
Fred Drake509d79a2000-07-08 04:04:38 +00002500Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002501{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002502 //CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00002503 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002504 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002505 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002506 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002507 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002508}
2509
2510static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002511Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002512{
Guido van Rossum35d43371997-08-02 00:09:09 +00002513 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002514}
2515
2516static PyTypeObject Tkapp_Type =
2517{
Guido van Rossum35d43371997-08-02 00:09:09 +00002518 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002519 0, /*ob_size */
2520 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002521 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002522 0, /*tp_itemsize */
2523 Tkapp_Dealloc, /*tp_dealloc */
2524 0, /*tp_print */
2525 Tkapp_GetAttr, /*tp_getattr */
2526 0, /*tp_setattr */
2527 0, /*tp_compare */
2528 0, /*tp_repr */
2529 0, /*tp_as_number */
2530 0, /*tp_as_sequence */
2531 0, /*tp_as_mapping */
2532 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002533};
2534
Barry Warsawfa701a81997-01-16 00:15:11 +00002535
2536
Guido van Rossum18468821994-06-20 07:49:28 +00002537/**** Tkinter Module ****/
2538
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002539typedef struct {
2540 PyObject* tuple;
2541 int size; /* current size */
2542 int maxsize; /* allocated size */
2543} FlattenContext;
2544
2545static int
2546_bump(FlattenContext* context, int size)
2547{
Guido van Rossum2834b972000-10-06 16:58:26 +00002548 /* expand tuple to hold (at least) size new items.
2549 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002550
2551 int maxsize = context->maxsize * 2;
2552
2553 if (maxsize < context->size + size)
2554 maxsize = context->size + size;
2555
2556 context->maxsize = maxsize;
2557
Tim Peters4324aa32001-05-28 22:30:08 +00002558 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002559}
2560
2561static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002562_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002563{
2564 /* add tuple or list to argument tuple (recursively) */
2565
2566 int i, size;
2567
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002568 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002569 PyErr_SetString(PyExc_ValueError,
2570 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002571 return 0;
2572 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002573 size = PyList_GET_SIZE(item);
2574 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002575 if (context->size + size > context->maxsize &&
2576 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002577 return 0;
2578 /* copy items to output tuple */
2579 for (i = 0; i < size; i++) {
2580 PyObject *o = PyList_GET_ITEM(item, i);
2581 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002582 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002583 return 0;
2584 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002585 if (context->size + 1 > context->maxsize &&
2586 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002587 return 0;
2588 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002589 PyTuple_SET_ITEM(context->tuple,
2590 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002591 }
2592 }
2593 } else if (PyTuple_Check(item)) {
2594 /* same, for tuples */
2595 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002596 if (context->size + size > context->maxsize &&
2597 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002598 return 0;
2599 for (i = 0; i < size; i++) {
2600 PyObject *o = PyTuple_GET_ITEM(item, i);
2601 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002602 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002603 return 0;
2604 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002605 if (context->size + 1 > context->maxsize &&
2606 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002607 return 0;
2608 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002609 PyTuple_SET_ITEM(context->tuple,
2610 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002611 }
2612 }
2613 } else {
2614 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2615 return 0;
2616 }
2617 return 1;
2618}
2619
2620static PyObject *
2621Tkinter_Flatten(PyObject* self, PyObject* args)
2622{
2623 FlattenContext context;
2624 PyObject* item;
2625
2626 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2627 return NULL;
2628
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002629 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002630 if (context.maxsize <= 0)
2631 return PyTuple_New(0);
2632
2633 context.tuple = PyTuple_New(context.maxsize);
2634 if (!context.tuple)
2635 return NULL;
2636
2637 context.size = 0;
2638
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002639 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002640 return NULL;
2641
Tim Peters4324aa32001-05-28 22:30:08 +00002642 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002643 return NULL;
2644
2645 return context.tuple;
2646}
2647
Guido van Rossum18468821994-06-20 07:49:28 +00002648static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002649Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002650{
Barry Warsawfa701a81997-01-16 00:15:11 +00002651 char *screenName = NULL;
2652 char *baseName = NULL;
2653 char *className = NULL;
2654 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002655 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002656
Guido van Rossum35d43371997-08-02 00:09:09 +00002657 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002658 if (baseName != NULL)
2659 baseName++;
2660 else
2661 baseName = Py_GetProgramName();
2662 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002663
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002664 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002665 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002666 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002667 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002668
Barry Warsawfa701a81997-01-16 00:15:11 +00002669 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002670 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002671}
2672
2673static PyMethodDef moduleMethods[] =
2674{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002675 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2676 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002677#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002678 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2679 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002680#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002681 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2682 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2683 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2684 {"quit", Tkapp_Quit, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002685 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002686};
2687
Guido van Rossum7bf15641998-05-22 18:28:17 +00002688#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002689
2690static int stdin_ready = 0;
2691
Guido van Rossumad4db171998-06-13 13:56:28 +00002692#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002693static void
Fred Drake509d79a2000-07-08 04:04:38 +00002694MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002695{
2696 stdin_ready = 1;
2697}
Guido van Rossumad4db171998-06-13 13:56:28 +00002698#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002699
Guido van Rossum00d93061998-05-28 23:06:38 +00002700static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002701
Guido van Rossum18468821994-06-20 07:49:28 +00002702static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002703EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002704{
Guido van Rossumad4db171998-06-13 13:56:28 +00002705#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002706 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002707#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002708#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002709 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002710#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002711 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002712 errorInCmd = 0;
2713#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002714 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002715 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002716#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002717 while (!errorInCmd && !stdin_ready) {
2718 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002719#ifdef MS_WINDOWS
2720 if (_kbhit()) {
2721 stdin_ready = 1;
2722 break;
2723 }
2724#endif
2725#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002726 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002727 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002728 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002729
Guido van Rossum00d93061998-05-28 23:06:38 +00002730 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002731
2732 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002733 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002734 if (result == 0)
2735 Sleep(20);
2736 Py_END_ALLOW_THREADS
2737#else
2738 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002739#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002740
2741 if (result < 0)
2742 break;
2743 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002744#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002745 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002746#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002747 if (errorInCmd) {
2748 errorInCmd = 0;
2749 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2750 excInCmd = valInCmd = trbInCmd = NULL;
2751 PyErr_Print();
2752 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002753#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002754 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002755#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002756 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002757}
Guido van Rossum18468821994-06-20 07:49:28 +00002758
Guido van Rossum00d93061998-05-28 23:06:38 +00002759#endif
2760
Guido van Rossum7bf15641998-05-22 18:28:17 +00002761static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002762EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002763{
Guido van Rossum00d93061998-05-28 23:06:38 +00002764#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002765 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002766#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002767 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002768#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002769 PyOS_InputHook = EventHook;
2770 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002771#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002772}
2773
2774static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002775DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002776{
Guido van Rossum00d93061998-05-28 23:06:38 +00002777#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002778 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2779 PyOS_InputHook = NULL;
2780 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002781#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002782}
2783
Barry Warsawfa701a81997-01-16 00:15:11 +00002784
2785/* all errors will be checked in one fell swoop in init_tkinter() */
2786static void
Fred Drake509d79a2000-07-08 04:04:38 +00002787ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002788{
2789 PyObject *v = PyInt_FromLong(val);
2790 if (v) {
2791 PyDict_SetItemString(d, name, v);
2792 Py_DECREF(v);
2793 }
2794}
2795static void
Fred Drake509d79a2000-07-08 04:04:38 +00002796ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002797{
2798 PyObject *v = PyString_FromString(val);
2799 if (v) {
2800 PyDict_SetItemString(d, name, v);
2801 Py_DECREF(v);
2802 }
2803}
2804
2805
Mark Hammond62b1ab12002-07-23 06:31:15 +00002806PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002807init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002808{
Barry Warsawfa701a81997-01-16 00:15:11 +00002809 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002810
Barry Warsawfa701a81997-01-16 00:15:11 +00002811 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002812
2813#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002814 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002815#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002816
Barry Warsawfa701a81997-01-16 00:15:11 +00002817 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002818
Barry Warsawfa701a81997-01-16 00:15:11 +00002819 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00002820 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00002821 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002822
Guido van Rossum35d43371997-08-02 00:09:09 +00002823 ins_long(d, "READABLE", TCL_READABLE);
2824 ins_long(d, "WRITABLE", TCL_WRITABLE);
2825 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2826 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2827 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2828 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2829 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2830 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2831 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002832 ins_string(d, "TK_VERSION", TK_VERSION);
2833 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002834
Guido van Rossum83551bf1997-09-13 00:44:23 +00002835 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002836
2837 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002838 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2839
Martin v. Löwisffad6332002-11-26 09:28:05 +00002840 PyTclObject_Type.ob_type = &PyType_Type;
2841 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002842
2843#ifdef TK_AQUA
2844 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2845 * start waking up. Note that Tcl_FindExecutable will do this, this
2846 * code must be above it! The original warning from
2847 * tkMacOSXAppInit.c is copied below.
2848 *
2849 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2850 * Tcl interpreter for now. It probably should work to do this
2851 * in the other order, but for now it doesn't seem to.
2852 *
2853 */
2854 Tk_MacOSXSetupTkNotifier();
2855#endif
2856
2857
Guido van Rossume187b0e2000-03-27 21:46:29 +00002858 /* This helps the dynamic loader; in Unicode aware Tcl versions
2859 it also helps Tcl find its encodings. */
2860 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00002861
Barry Warsawfa701a81997-01-16 00:15:11 +00002862 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002863 return;
2864
Guido van Rossum43ff8681998-07-14 18:02:13 +00002865#if 0
2866 /* This was not a good idea; through <Destroy> bindings,
2867 Tcl_Finalize() may invoke Python code but at that point the
2868 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002869 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002870#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002871
Jack Jansen34cc5c31995-10-31 16:15:12 +00002872#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002873 /*
2874 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2875 ** Most of the initializations in that routine (toolbox init calls and
2876 ** such) have already been done for us, so we only need these.
2877 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002878 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002879
2880 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00002881#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00002882 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00002883#endif /* GENERATINGCFM */
2884#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00002885}
Guido van Rossum9722ad81995-09-22 23:49:28 +00002886
Guido van Rossumec22c921996-02-25 04:50:29 +00002887
Barry Warsawfa701a81997-01-16 00:15:11 +00002888
Guido van Rossum9722ad81995-09-22 23:49:28 +00002889#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002890
2891/*
Guido van Rossumec22c921996-02-25 04:50:29 +00002892** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002893*/
2894
Guido van Rossum9722ad81995-09-22 23:49:28 +00002895void
2896panic(char * format, ...)
2897{
Barry Warsawfa701a81997-01-16 00:15:11 +00002898 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002899
Barry Warsawfa701a81997-01-16 00:15:11 +00002900 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002901
Guido van Rossum227cf761998-08-05 13:53:32 +00002902 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002903 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002904
Barry Warsawfa701a81997-01-16 00:15:11 +00002905 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002906
Barry Warsawfa701a81997-01-16 00:15:11 +00002907 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00002908}
Jack Jansen40b546d1995-11-14 10:34:45 +00002909
Guido van Rossumec22c921996-02-25 04:50:29 +00002910/*
2911** Pass events to SIOUX before passing them to Tk.
2912*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002913
Guido van Rossumec22c921996-02-25 04:50:29 +00002914static int
Fred Drake509d79a2000-07-08 04:04:38 +00002915PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002916{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002917 WindowPtr frontwin;
2918 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00002919 ** Sioux eats too many events, so we don't pass it everything. We
2920 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002921 ** the Sioux window is frontmost. This means that Tk menus don't work
2922 ** in that case, but at least we can scroll the sioux window.
2923 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2924 ** part of the external interface of Sioux...
2925 */
2926 frontwin = FrontWindow();
2927 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
2928 if (SIOUXHandleOneEvent(eventPtr))
2929 return 0; /* Nothing happened to the Tcl event queue */
2930 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002931 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002932}
2933
Guido van Rossumec22c921996-02-25 04:50:29 +00002934#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002935
2936/*
2937** Additional Mac specific code for dealing with shared libraries.
2938*/
2939
2940#include <Resources.h>
2941#include <CodeFragments.h>
2942
2943static int loaded_from_shlib = 0;
2944static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002945
Jack Jansen34cc5c31995-10-31 16:15:12 +00002946/*
2947** If this module is dynamically loaded the following routine should
2948** be the init routine. It takes care of adding the shared library to
2949** the resource-file chain, so that the tk routines can find their
2950** resources.
2951*/
2952OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002953init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002954{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00002955 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00002956 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002957 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002958 library_fss = *data->fragLocator.u.onDisk.fileSpec;
2959 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002960 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002961 library_fss = *data->fragLocator.u.inSegs.fileSpec;
2962 loaded_from_shlib = 1;
2963 }
2964 return noErr;
2965}
2966
2967/*
2968** Insert the library resources into the search path. Put them after
2969** the resources from the application. Again, we ignore errors.
2970*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002971static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002972mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002973{
2974 if ( !loaded_from_shlib )
2975 return;
2976 (void)FSpOpenResFile(&library_fss, fsRdPerm);
2977}
2978
Guido van Rossumec22c921996-02-25 04:50:29 +00002979#endif /* GENERATINGCFM */
2980#endif /* macintosh */