blob: d6407e26cfb4defa4f43886899ca3d72c233598d [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000012 Only Tcl/Tk 8.2 and later are supported. Older versions are not
13 supported. (Use Python 2.2 if you cannot upgrade your Tcl/Tk
Guido van Rossuma80649b2000-03-28 20:07:05 +000014 libraries.)
15*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Guido van Rossumbf0dc9f1996-08-20 20:49:56 +000036#ifdef macintosh
37#define MAC_TCL
Guido van Rossum49b56061998-10-01 20:42:43 +000038#endif
39
Martin v. Löwis71e25a02002-10-01 18:08:06 +000040/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
41 making _tkinter correct for this API means to break earlier
42 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
43 earlier versions. Once Tcl releases before 8.4 don't need to be supported
44 anymore, this should go. */
45#define USE_COMPAT_CONST
46
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000047/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
48 it always; if Tcl is not threaded, the thread functions in
49 Tcl are empty. */
50#define TCL_THREADS
51
Jack Jansencb852442001-12-09 23:15:56 +000052#ifdef TK_FRAMEWORK
53#include <Tcl/tcl.h>
54#include <Tk/tk.h>
55#else
Guido van Rossum18468821994-06-20 07:49:28 +000056#include <tcl.h>
57#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000058#endif
Guido van Rossum18468821994-06-20 07:49:28 +000059
Jason Tishlerbbe89612002-12-31 20:30:46 +000060/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000061#ifndef CONST84_RETURN
62#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000063#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000064#define CONST
65#endif
66
Guido van Rossum3e819a71997-08-01 19:29:02 +000067#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
68
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000069#if TKMAJORMINOR < 8002
70#error "Tk older than 8.2 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000071#endif
72
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000073/* Unicode conversion assumes that Tcl_UniChar is two bytes.
74 We cannot test this directly, so we test UTF-8 size instead,
75 expecting that TCL_UTF_MAX is changed if Tcl ever supports
76 either UTF-16 or UCS-4. */
77#if TCL_UTF_MAX != 3
78#error "unsupported Tcl configuration"
79#endif
80
Guido van Rossuma80649b2000-03-28 20:07:05 +000081#if defined(macintosh)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000082/* Sigh, we have to include this to get at the tcl qd pointer */
83#include <tkMac.h>
Guido van Rossum2ea1c941998-04-28 16:12:43 +000084/* And this one we need to clear the menu bar */
85#include <Menus.h>
Guido van Rossum0d2390c1997-08-14 19:57:07 +000086#endif
87
Jack Jansen84c10b12001-07-16 19:32:52 +000088#if !(defined(MS_WINDOWS) || defined(__CYGWIN__) || defined(macintosh))
89/* Mac has it, but it doesn't really work:-( */
Guido van Rossum0d2390c1997-08-14 19:57:07 +000090#define HAVE_CREATEFILEHANDLER
91#endif
92
Guido van Rossum00d93061998-05-28 23:06:38 +000093#ifdef HAVE_CREATEFILEHANDLER
94
95/* Tcl_CreateFileHandler() changed several times; these macros deal with the
96 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
97 Unix, only because Jack added it back); when available on Windows, it only
98 applies to sockets. */
99
Guido van Rossum7bf15641998-05-22 18:28:17 +0000100#ifdef MS_WINDOWS
101#define FHANDLETYPE TCL_WIN_SOCKET
102#else
103#define FHANDLETYPE TCL_UNIX_FD
104#endif
105
Guido van Rossum00d93061998-05-28 23:06:38 +0000106/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
107 which uses this to handle Tcl events while the user is typing commands. */
108
109#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000110#define WAIT_FOR_STDIN
111#endif
112
Guido van Rossum00d93061998-05-28 23:06:38 +0000113#endif /* HAVE_CREATEFILEHANDLER */
114
Guido van Rossumad4db171998-06-13 13:56:28 +0000115#ifdef MS_WINDOWS
116#include <conio.h>
117#define WAIT_FOR_STDIN
118#endif
119
Guido van Rossum00d93061998-05-28 23:06:38 +0000120#ifdef WITH_THREAD
121
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000122/* The threading situation is complicated. Tcl is not thread-safe, except
123 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000124 So we need to use a lock around all uses of Tcl. Previously, the Python
125 interpreter lock was used for this. However, this causes problems when
126 other Python threads need to run while Tcl is blocked waiting for events.
127
128 To solve this problem, a separate lock for Tcl is introduced. Holding it
129 is incompatible with holding Python's interpreter lock. The following four
130 macros manipulate both locks together.
131
132 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
133 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
134 that could call an event handler, or otherwise affect the state of a Tcl
135 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000136 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000137 released and the lock for Tcl has been acquired.
138
Guido van Rossum5e977831998-06-15 14:03:52 +0000139 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
140 (For example, when transferring data from the Tcl interpreter result to a
141 Python string object.) This can be done by using different macros to close
142 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
143 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
144 releases the Tcl lock.
145
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000146 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000147 handlers when the handler needs to use Python. Such event handlers are
148 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000149 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000150 the Python interpreter lock, restoring the appropriate thread state, and
151 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
152 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000153 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000154
155 These locks expand to several statements and brackets; they should not be
156 used in branches of if statements and the like.
157
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000158 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
159 only valid in the thread that created it, and all Tk activity must happen in this
160 thread, also. That means that the mainloop must be invoked in the thread that
161 created the interpreter. Invoking commands from other threads is possible;
162 _tkinter will queue an event for the interpreter thread, which will then
163 execute the command and pass back the result. If the main thread is not in the
164 mainloop, and invoking commands causes an exception; if the main loop is running
165 but not processing events, the command invocation will block.
166
167 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
168 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
169 threads. So we use the Tcl TLS API.
170
Guido van Rossum00d93061998-05-28 23:06:38 +0000171*/
172
Guido van Rossum65d5b571998-12-21 19:32:43 +0000173static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000174
175#ifdef TCL_THREADS
176static Tcl_ThreadDataKey state_key;
177typedef PyThreadState *ThreadSpecificData;
178#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
179#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000180static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000181#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000182
183#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000184 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000185 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000186
187#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000188 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000189
Guido van Rossum62320c91998-06-15 04:36:09 +0000190#define ENTER_OVERLAP \
191 Py_END_ALLOW_THREADS
192
193#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000194 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000195
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000196#define ENTER_PYTHON \
197 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000198 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000199
200#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000201 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000202 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
203
204#define CHECK_TCL_APPARTMENT \
205 if (((TkappObject *)self)->threaded && \
206 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
207 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
208 return 0; \
209 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000210
211#else
212
213#define ENTER_TCL
214#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000215#define ENTER_OVERLAP
216#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000217#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000218#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000219#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000220
221#endif
222
Guido van Rossumec22c921996-02-25 04:50:29 +0000223#ifdef macintosh
224
225/*
226** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000227** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000228*/
229
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000230/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000231#define FREECAST (char *)
232
Guido van Rossumec22c921996-02-25 04:50:29 +0000233#include <Events.h> /* For EventRecord */
234
Fred Drake509d79a2000-07-08 04:04:38 +0000235typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
Guido van Rossum2834b972000-10-06 16:58:26 +0000236void Tcl_MacSetEventProc(TclMacConvertEventPtr procPtr);
237int TkMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000238
Jeremy Hylton938ace62002-07-17 16:30:39 +0000239static int PyMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000240
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000241#include <SIOUX.h>
242extern int SIOUXIsAppWindow(WindowPtr);
243
Guido van Rossumec22c921996-02-25 04:50:29 +0000244#endif /* macintosh */
245
Guido van Rossum97867b21996-08-08 19:09:53 +0000246#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000247#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000248#endif
249
Guido van Rossum18468821994-06-20 07:49:28 +0000250/**** Tkapp Object Declaration ****/
251
Jeremy Hylton938ace62002-07-17 16:30:39 +0000252static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000253
Guido van Rossum00d93061998-05-28 23:06:38 +0000254typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000255 PyObject_HEAD
256 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000257 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000258 int threaded; /* True if tcl_platform[threaded] */
259 Tcl_ThreadId thread_id;
260 int dispatching;
261 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000262 So we cache interesting types here. */
263 Tcl_ObjType *BooleanType;
264 Tcl_ObjType *ByteArrayType;
265 Tcl_ObjType *DoubleType;
266 Tcl_ObjType *IntType;
267 Tcl_ObjType *ListType;
268 Tcl_ObjType *ProcBodyType;
269 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000270} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000271
272#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000273#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000274#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000275
Guido van Rossum35d43371997-08-02 00:09:09 +0000276#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000277(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000278
Barry Warsawfa701a81997-01-16 00:15:11 +0000279
280
Guido van Rossum18468821994-06-20 07:49:28 +0000281/**** Error Handling ****/
282
283static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000284static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000285static int errorInCmd = 0;
286static PyObject *excInCmd;
287static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000288static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000289
Barry Warsawfa701a81997-01-16 00:15:11 +0000290
291
Guido van Rossum18468821994-06-20 07:49:28 +0000292static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000293Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000294{
Barry Warsawfa701a81997-01-16 00:15:11 +0000295 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
296 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000297}
298
Barry Warsawfa701a81997-01-16 00:15:11 +0000299
Barry Warsawfa701a81997-01-16 00:15:11 +0000300
Guido van Rossum18468821994-06-20 07:49:28 +0000301/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000302
303#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000304#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000305
Guido van Rossum00d93061998-05-28 23:06:38 +0000306/* Millisecond sleep() for Unix platforms. */
307
308static void
Fred Drake509d79a2000-07-08 04:04:38 +0000309Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000310{
311 /* XXX Too bad if you don't have select(). */
312 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000313 t.tv_sec = milli/1000;
314 t.tv_usec = (milli%1000) * 1000;
315 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
316}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000317#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000318#endif /* WITH_THREAD */
319
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000320/* Wait up to 1s for the mainloop to come up. */
321
322static int
323WaitForMainloop(TkappObject* self)
324{
325 int i;
326 for (i = 0; i < 10; i++) {
327 if (self->dispatching)
328 return 1;
329 Py_BEGIN_ALLOW_THREADS
330 Sleep(100);
331 Py_END_ALLOW_THREADS
332 }
333 if (self->dispatching)
334 return 1;
335 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
336 return 0;
337}
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000338
Guido van Rossum00d93061998-05-28 23:06:38 +0000339
Guido van Rossum18468821994-06-20 07:49:28 +0000340static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000341AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000342{
Guido van Rossum35d43371997-08-02 00:09:09 +0000343 if (PyString_Check(value))
344 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000345#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000346 else if (PyUnicode_Check(value)) {
347 PyObject *v = PyUnicode_AsUTF8String(value);
348 if (v == NULL)
349 return NULL;
350 if (PyList_Append(tmp, v) != 0) {
351 Py_DECREF(v);
352 return NULL;
353 }
354 Py_DECREF(v);
355 return PyString_AsString(v);
356 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000357#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000358 else {
359 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000360 if (v == NULL)
361 return NULL;
362 if (PyList_Append(tmp, v) != 0) {
363 Py_DECREF(v);
364 return NULL;
365 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000366 Py_DECREF(v);
367 return PyString_AsString(v);
368 }
Guido van Rossum18468821994-06-20 07:49:28 +0000369}
370
Barry Warsawfa701a81997-01-16 00:15:11 +0000371
372
Guido van Rossum18468821994-06-20 07:49:28 +0000373#define ARGSZ 64
374
375static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000376Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000377{
Barry Warsawfa701a81997-01-16 00:15:11 +0000378 PyObject *tmp = NULL;
379 char *argvStore[ARGSZ];
380 char **argv = NULL;
381 int fvStore[ARGSZ];
382 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000383 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000384 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000385
Barry Warsawfa701a81997-01-16 00:15:11 +0000386 if (!(tmp = PyList_New(0)))
387 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000388
Barry Warsawfa701a81997-01-16 00:15:11 +0000389 argv = argvStore;
390 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000391
Barry Warsawfa701a81997-01-16 00:15:11 +0000392 if (args == NULL)
393 argc = 0;
394
395 else if (!PyTuple_Check(args)) {
396 argc = 1;
397 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000398 if (!(argv[0] = AsString(args, tmp)))
399 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000400 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000401 else {
402 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000403
Barry Warsawfa701a81997-01-16 00:15:11 +0000404 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000405 argv = (char **)ckalloc(argc * sizeof(char *));
406 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000407 if (argv == NULL || fv == NULL) {
408 PyErr_NoMemory();
409 goto finally;
410 }
411 }
412
413 for (i = 0; i < argc; i++) {
414 PyObject *v = PyTuple_GetItem(args, i);
415 if (PyTuple_Check(v)) {
416 fv[i] = 1;
417 if (!(argv[i] = Merge(v)))
418 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000419 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000420 }
421 else if (v == Py_None) {
422 argc = i;
423 break;
424 }
425 else {
426 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000427 if (!(argv[i] = AsString(v, tmp)))
428 goto finally;
429 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000430 }
431 }
Guido van Rossum18468821994-06-20 07:49:28 +0000432 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000433 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000434 if (res == NULL)
435 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000436
Barry Warsawfa701a81997-01-16 00:15:11 +0000437 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000438 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000439 if (fv[i]) {
440 ckfree(argv[i]);
441 }
442 if (argv != argvStore)
443 ckfree(FREECAST argv);
444 if (fv != fvStore)
445 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000446
Barry Warsawfa701a81997-01-16 00:15:11 +0000447 Py_DECREF(tmp);
448 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000449}
450
Barry Warsawfa701a81997-01-16 00:15:11 +0000451
452
Guido van Rossum18468821994-06-20 07:49:28 +0000453static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000454Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000455{
Barry Warsawfa701a81997-01-16 00:15:11 +0000456 int argc;
457 char **argv;
458 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000459
Barry Warsawfa701a81997-01-16 00:15:11 +0000460 if (list == NULL) {
461 Py_INCREF(Py_None);
462 return Py_None;
463 }
Guido van Rossum18468821994-06-20 07:49:28 +0000464
Guido van Rossum00d93061998-05-28 23:06:38 +0000465 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000466 /* Not a list.
467 * Could be a quoted string containing funnies, e.g. {"}.
468 * Return the string itself.
469 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000470 return PyString_FromString(list);
471 }
Guido van Rossum18468821994-06-20 07:49:28 +0000472
Barry Warsawfa701a81997-01-16 00:15:11 +0000473 if (argc == 0)
474 v = PyString_FromString("");
475 else if (argc == 1)
476 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000477 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000478 int i;
479 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000480
Barry Warsawfa701a81997-01-16 00:15:11 +0000481 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000482 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000483 Py_DECREF(v);
484 v = NULL;
485 break;
486 }
487 PyTuple_SetItem(v, i, w);
488 }
489 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000490 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000491 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000492}
493
Martin v. Löwisffad6332002-11-26 09:28:05 +0000494/* In some cases, Tcl will still return strings that are supposed to be
495 lists. SplitObj walks through a nested tuple, finding string objects that
496 need to be split. */
497
498PyObject *
499SplitObj(PyObject *arg)
500{
501 if (PyTuple_Check(arg)) {
502 int i, size;
503 PyObject *elem, *newelem, *result;
504
505 size = PyTuple_Size(arg);
506 result = NULL;
507 /* Recursively invoke SplitObj for all tuple items.
508 If this does not return a new object, no action is
509 needed. */
510 for(i = 0; i < size; i++) {
511 elem = PyTuple_GetItem(arg, i);
512 newelem = SplitObj(elem);
513 if (!newelem) {
514 Py_XDECREF(result);
515 return NULL;
516 }
517 if (!result) {
518 int k;
519 if (newelem == elem) {
520 Py_DECREF(newelem);
521 continue;
522 }
523 result = PyTuple_New(size);
524 if (!result)
525 return NULL;
526 for(k = 0; k < i; k++) {
527 elem = PyTuple_GetItem(arg, k);
528 Py_INCREF(elem);
529 PyTuple_SetItem(result, k, elem);
530 }
531 }
532 PyTuple_SetItem(result, i, newelem);
533 }
534 if (result)
535 return result;
536 /* Fall through, returning arg. */
537 }
538 else if (PyString_Check(arg)) {
539 int argc;
540 char **argv;
541 char *list = PyString_AsString(arg);
542
543 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
544 Py_INCREF(arg);
545 return arg;
546 }
547 Tcl_Free(FREECAST argv);
548 if (argc > 1)
549 return Split(PyString_AsString(arg));
550 /* Fall through, returning arg. */
551 }
552 Py_INCREF(arg);
553 return arg;
554}
Barry Warsawfa701a81997-01-16 00:15:11 +0000555
556
Guido van Rossum18468821994-06-20 07:49:28 +0000557/**** Tkapp Object ****/
558
559#ifndef WITH_APPINIT
560int
Fred Drake509d79a2000-07-08 04:04:38 +0000561Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000562{
Barry Warsawfa701a81997-01-16 00:15:11 +0000563 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000564
Barry Warsawfa701a81997-01-16 00:15:11 +0000565 main = Tk_MainWindow(interp);
566 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000567 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000568 return TCL_ERROR;
569 }
570 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000571 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000572 return TCL_ERROR;
573 }
574 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000575}
576#endif /* !WITH_APPINIT */
577
Guido van Rossum18468821994-06-20 07:49:28 +0000578
Barry Warsawfa701a81997-01-16 00:15:11 +0000579
580
581/* Initialize the Tk application; see the `main' function in
582 * `tkMain.c'.
583 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000584
Thomas Wouters58d05102000-07-24 14:43:35 +0000585static void EnableEventHook(void); /* Forward */
586static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000587
Barry Warsawfa701a81997-01-16 00:15:11 +0000588static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000589Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000590 int interactive, int wantobjects)
Barry Warsawfa701a81997-01-16 00:15:11 +0000591{
592 TkappObject *v;
593 char *argv0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000594
Guido van Rossumb18618d2000-05-03 23:44:39 +0000595 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000596 if (v == NULL)
597 return NULL;
598
599 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000600 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000601 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
602 TCL_GLOBAL_ONLY) != NULL;
603 v->thread_id = Tcl_GetCurrentThread();
604 v->dispatching = 0;
605
606#ifndef TCL_THREADS
607 if (v->threaded) {
608 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
609 Py_DECREF(v);
610 return 0;
611 }
612#endif
613 if (v->threaded && tcl_lock) {
614 /* If Tcl is threaded, we don't need the lock. */
615 PyThread_free_lock(tcl_lock);
616 tcl_lock = NULL;
617 }
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000618
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000619 v->BooleanType = Tcl_GetObjType("boolean");
620 v->ByteArrayType = Tcl_GetObjType("bytearray");
621 v->DoubleType = Tcl_GetObjType("double");
622 v->IntType = Tcl_GetObjType("int");
623 v->ListType = Tcl_GetObjType("list");
624 v->ProcBodyType = Tcl_GetObjType("procbody");
625 v->StringType = Tcl_GetObjType("string");
626
Guido van Rossuma80649b2000-03-28 20:07:05 +0000627#if defined(macintosh)
628 /* This seems to be needed */
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000629 ClearMenuBar();
630 TkMacInitMenus(v->interp);
631#endif
Jack Jansencb852442001-12-09 23:15:56 +0000632
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000633 /* Delete the 'exit' command, which can screw things up */
634 Tcl_DeleteCommand(v->interp, "exit");
635
Barry Warsawfa701a81997-01-16 00:15:11 +0000636 if (screenName != NULL)
637 Tcl_SetVar2(v->interp, "env", "DISPLAY",
638 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000639
Barry Warsawfa701a81997-01-16 00:15:11 +0000640 if (interactive)
641 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
642 else
643 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000644
Barry Warsawfa701a81997-01-16 00:15:11 +0000645 /* This is used to get the application class for Tk 4.1 and up */
646 argv0 = (char*)ckalloc(strlen(className) + 1);
647 if (!argv0) {
648 PyErr_NoMemory();
649 Py_DECREF(v);
650 return NULL;
651 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000652
Barry Warsawfa701a81997-01-16 00:15:11 +0000653 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000654 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000655 argv0[0] = tolower(argv0[0]);
656 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
657 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000658
Barry Warsawfa701a81997-01-16 00:15:11 +0000659 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000660 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000661
Guido van Rossum7bf15641998-05-22 18:28:17 +0000662 EnableEventHook();
663
Barry Warsawfa701a81997-01-16 00:15:11 +0000664 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000665}
666
Barry Warsawfa701a81997-01-16 00:15:11 +0000667
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000668static void
669Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
670 Tcl_Condition *cond, Tcl_Mutex *mutex)
671{
672 Py_BEGIN_ALLOW_THREADS;
673 Tcl_MutexLock(mutex);
674 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
675 Tcl_ThreadAlert(self->thread_id);
676 Tcl_ConditionWait(cond, mutex, NULL);
677 Tcl_MutexUnlock(mutex);
678 Py_END_ALLOW_THREADS
679}
680
Barry Warsawfa701a81997-01-16 00:15:11 +0000681
Guido van Rossum18468821994-06-20 07:49:28 +0000682/** Tcl Eval **/
683
Martin v. Löwisffad6332002-11-26 09:28:05 +0000684typedef struct {
685 PyObject_HEAD
686 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000687 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000688} PyTclObject;
689
690staticforward PyTypeObject PyTclObject_Type;
691#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
692
693static PyObject *
694newPyTclObject(Tcl_Obj *arg)
695{
696 PyTclObject *self;
697 self = PyObject_New(PyTclObject, &PyTclObject_Type);
698 if (self == NULL)
699 return NULL;
700 Tcl_IncrRefCount(arg);
701 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000702 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000703 return (PyObject*)self;
704}
705
706static void
707PyTclObject_dealloc(PyTclObject *self)
708{
709 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000710 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000711 PyObject_Del(self);
712}
713
714static PyObject *
715PyTclObject_str(PyTclObject *self)
716{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000717 if (self->string && PyString_Check(self->string)) {
718 Py_INCREF(self->string);
719 return self->string;
720 }
721 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000722 return PyString_FromString(Tcl_GetString(self->value));
723}
724
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000725/* Like _str, but create Unicode if necessary. */
726static PyObject *
727PyTclObject_string(PyTclObject *self, void *ignored)
728{
729 char *s;
730 int i, len;
731 if (!self->string) {
732 s = Tcl_GetStringFromObj(self->value, &len);
733 for (i = 0; i < len; i++)
734 if (s[i] & 0x80)
735 break;
736#ifdef Py_USING_UNICODE
737 if (i == len)
738 /* It is an ASCII string. */
739 self->string = PyString_FromStringAndSize(s, len);
740 else {
741 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
742 if (!self->string) {
743 PyErr_Clear();
744 self->string = PyString_FromStringAndSize(s, len);
745 }
746 }
747#else
748 self->string = PyString_FromStringAndSize(s, len);
749#endif
750 if (!self->string)
751 return NULL;
752 }
753 Py_INCREF(self->string);
754 return self->string;
755}
756
757#ifdef Py_USING_UNICODE
758static PyObject *
759PyTclObject_unicode(PyTclObject *self, void *ignored)
760{
761 char *s;
762 int len;
763 if (self->string && PyUnicode_Check(self->string)) {
764 Py_INCREF(self->string);
765 return self->string;
766 }
767 /* XXX Could chache result if it is non-ASCII. */
768 s = Tcl_GetStringFromObj(self->value, &len);
769 return PyUnicode_DecodeUTF8(s, len, "strict");
770}
771#endif
772
Martin v. Löwisffad6332002-11-26 09:28:05 +0000773static PyObject *
774PyTclObject_repr(PyTclObject *self)
775{
776 char buf[50];
777 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
778 self->value->typePtr->name, (int)self->value);
779 return PyString_FromString(buf);
780}
781
782static PyObject*
783get_typename(PyTclObject* obj, void* ignored)
784{
785 return PyString_FromString(obj->value->typePtr->name);
786}
787
788static PyGetSetDef PyTclObject_getsetlist[] = {
789 {"typename", (getter)get_typename, NULL, "name of the Tcl type"},
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000790 {"string", (getter)PyTclObject_string, NULL, "name of the Tcl type"},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000791 {0},
792};
793
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000794static PyMethodDef PyTclObject_methods[] = {
795 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
796 "convert argument to unicode"},
797 {0}
798};
799
Martin v. Löwisffad6332002-11-26 09:28:05 +0000800statichere PyTypeObject PyTclObject_Type = {
801 PyObject_HEAD_INIT(NULL)
802 0, /*ob_size*/
803 "_tkinter.Tcl_Obj", /*tp_name*/
804 sizeof(PyTclObject), /*tp_basicsize*/
805 0, /*tp_itemsize*/
806 /* methods */
807 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
808 0, /*tp_print*/
809 0, /*tp_getattr*/
810 0, /*tp_setattr*/
811 0, /*tp_compare*/
812 (reprfunc)PyTclObject_repr, /*tp_repr*/
813 0, /*tp_as_number*/
814 0, /*tp_as_sequence*/
815 0, /*tp_as_mapping*/
816 0, /*tp_hash*/
817 0, /*tp_call*/
818 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerbbe89612002-12-31 20:30:46 +0000819 0, /*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000820 0, /*tp_setattro*/
821 0, /*tp_as_buffer*/
822 Py_TPFLAGS_DEFAULT, /*tp_flags*/
823 0, /*tp_doc*/
824 0, /*tp_traverse*/
825 0, /*tp_clear*/
826 0, /*tp_richcompare*/
827 0, /*tp_weaklistoffset*/
828 0, /*tp_iter*/
829 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000830 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000831 0, /*tp_members*/
832 PyTclObject_getsetlist, /*tp_getset*/
833 0, /*tp_base*/
834 0, /*tp_dict*/
835 0, /*tp_descr_get*/
836 0, /*tp_descr_set*/
837 0, /*tp_dictoffset*/
838 0, /*tp_init*/
839 0, /*tp_alloc*/
840 0, /*tp_new*/
841 0, /*tp_free*/
842 0, /*tp_is_gc*/
843};
844
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000845static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000846AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000847{
848 Tcl_Obj *result;
849
850 if (PyString_Check(value))
851 return Tcl_NewStringObj(PyString_AS_STRING(value),
852 PyString_GET_SIZE(value));
853 else if (PyInt_Check(value))
854 return Tcl_NewLongObj(PyInt_AS_LONG(value));
855 else if (PyFloat_Check(value))
856 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
857 else if (PyTuple_Check(value)) {
858 Tcl_Obj **argv = (Tcl_Obj**)
859 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
860 int i;
861 if(!argv)
862 return 0;
863 for(i=0;i<PyTuple_Size(value);i++)
864 argv[i] = AsObj(PyTuple_GetItem(value,i));
865 result = Tcl_NewListObj(PyTuple_Size(value), argv);
866 ckfree(FREECAST argv);
867 return result;
868 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000869#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000870 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000871 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
872 int size = PyUnicode_GET_SIZE(value);
873 /* This #ifdef assumes that Tcl uses UCS-2.
874 See TCL_UTF_MAX test above. */
875#ifdef Py_UNICODE_WIDE
876 Tcl_UniChar *outbuf;
877 int i;
878 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
879 if (!outbuf) {
880 PyErr_NoMemory();
881 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000882 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000883 for (i = 0; i < size; i++) {
884 if (inbuf[i] >= 0x10000) {
885 /* Tcl doesn't do UTF-16, yet. */
886 PyErr_SetString(PyExc_ValueError,
887 "unsupported character");
888 ckfree(FREECAST outbuf);
889 return NULL;
890 }
891 outbuf[i] = inbuf[i];
892 }
893 result = Tcl_NewUnicodeObj(outbuf, size);
894 ckfree(FREECAST outbuf);
895 return result;
896#else
897 return Tcl_NewUnicodeObj(inbuf, size);
898#endif
899
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000900 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000901#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000902 else if(PyTclObject_Check(value)) {
903 Tcl_Obj *v = ((PyTclObject*)value)->value;
904 Tcl_IncrRefCount(v);
905 return v;
906 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000907 else {
908 PyObject *v = PyObject_Str(value);
909 if (!v)
910 return 0;
911 result = AsObj(v);
912 Py_DECREF(v);
913 return result;
914 }
915}
916
Martin v. Löwisffad6332002-11-26 09:28:05 +0000917static PyObject*
918FromObj(PyObject* tkapp, Tcl_Obj *value)
919{
920 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000921 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000922
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000923 if (value->typePtr == NULL) {
924 /* If the result contains any bytes with the top bit set,
925 it's UTF-8 and we should decode it to Unicode */
926#ifdef Py_USING_UNICODE
927 int i;
928 char *s = value->bytes;
929 int len = value->length;
930 for (i = 0; i < len; i++) {
931 if (value->bytes[i] & 0x80)
932 break;
933 }
934
935 if (i == value->length)
936 result = PyString_FromStringAndSize(s, len);
937 else {
938 /* Convert UTF-8 to Unicode string */
939 result = PyUnicode_DecodeUTF8(s, len, "strict");
940 if (result == NULL) {
941 PyErr_Clear();
942 result = PyString_FromStringAndSize(s, len);
943 }
944 }
945#else
946 res = PyString_FromStringAndSize(value->bytes, value->length);
947#endif
948 return result;
949 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000950
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000951 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000952 result = value->internalRep.longValue ? Py_True : Py_False;
953 Py_INCREF(result);
954 return result;
955 }
956
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000957 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000958 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000959 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000960 return PyString_FromStringAndSize(data, size);
961 }
962
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000963 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000964 return PyFloat_FromDouble(value->internalRep.doubleValue);
965 }
966
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000967 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000968 return PyInt_FromLong(value->internalRep.longValue);
969 }
970
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000971 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000972 int size;
973 int i, status;
974 PyObject *elem;
975 Tcl_Obj *tcl_elem;
976
977 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
978 if (status == TCL_ERROR)
979 return Tkinter_Error(tkapp);
980 result = PyTuple_New(size);
981 if (!result)
982 return NULL;
983 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000984 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +0000985 value, i, &tcl_elem);
986 if (status == TCL_ERROR) {
987 Py_DECREF(result);
988 return Tkinter_Error(tkapp);
989 }
990 elem = FromObj(tkapp, tcl_elem);
991 if (!elem) {
992 Py_DECREF(result);
993 return NULL;
994 }
995 PyTuple_SetItem(result, i, elem);
996 }
997 return result;
998 }
999
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001000 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001001 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001002 }
1003
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001004 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001005#ifdef Py_USING_UNICODE
1006#ifdef Py_UNICODE_WIDE
1007 PyObject *result;
1008 int size;
1009 Tcl_UniChar *input;
1010 Py_UNICODE *output;
1011
1012 size = Tcl_GetCharLength(value);
1013 result = PyUnicode_FromUnicode(NULL, size);
1014 if (!result)
1015 return NULL;
1016 input = Tcl_GetUnicode(value);
1017 output = PyUnicode_AS_UNICODE(result);
1018 while (size--)
1019 *output++ = *input++;
1020 return result;
1021#else
1022 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1023 Tcl_GetCharLength(value));
1024#endif
1025#else
1026 int size;
1027 char *c;
1028 c = Tcl_GetStringFromObj(value, &size);
1029 return PyString_FromStringAndSize(c, size);
1030#endif
1031 }
1032
1033 return newPyTclObject(value);
1034}
1035
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001036/* This mutex synchronizes inter-thread command calls. */
1037
1038TCL_DECLARE_MUTEX(call_mutex)
1039
1040typedef struct Tkapp_CallEvent {
1041 Tcl_Event ev; /* Must be first */
1042 TkappObject *self;
1043 PyObject *args;
1044 int flags;
1045 PyObject **res;
1046 PyObject **exc_type, **exc_value, **exc_tb;
1047 Tcl_Condition done;
1048} Tkapp_CallEvent;
1049
1050void
1051Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001052{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001053 int i;
1054 for (i = 0; i < objc; i++)
1055 Tcl_DecrRefCount(objv[i]);
1056 if (objv != objStore)
1057 ckfree(FREECAST objv);
1058}
Guido van Rossum18468821994-06-20 07:49:28 +00001059
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001060/* Convert Python objects to Tcl objects. This must happen in the
1061 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001062
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001063static Tcl_Obj**
1064Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1065{
1066 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001067 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001068 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001069 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001070
Guido van Rossum212643f1998-04-29 16:22:14 +00001071 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001072 objv[0] = AsObj(args);
1073 if (objv[0] == 0)
1074 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001075 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001076 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001077 }
1078 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001079 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001080
Guido van Rossum632de272000-03-29 00:19:50 +00001081 if (objc > ARGSZ) {
1082 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1083 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001084 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001085 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001086 goto finally;
1087 }
1088 }
1089
Guido van Rossum632de272000-03-29 00:19:50 +00001090 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001091 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001092 if (v == Py_None) {
1093 objc = i;
1094 break;
1095 }
Guido van Rossum632de272000-03-29 00:19:50 +00001096 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001097 if (!objv[i]) {
1098 /* Reset objc, so it attempts to clear
1099 objects only up to i. */
1100 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001101 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001102 }
Guido van Rossum632de272000-03-29 00:19:50 +00001103 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001104 }
1105 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001106 *pobjc = objc;
1107 return objv;
1108finally:
1109 Tkapp_CallDeallocArgs(objv, objStore, objc);
1110 return NULL;
1111}
Guido van Rossum212643f1998-04-29 16:22:14 +00001112
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001113/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001114
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001115static PyObject*
1116Tkapp_CallResult(TkappObject *self)
1117{
1118 PyObject *res = NULL;
1119 if(self->wantobjects) {
1120 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001121 /* Not sure whether the IncrRef is necessary, but something
1122 may overwrite the interpreter result while we are
1123 converting it. */
1124 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001125 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001126 Tcl_DecrRefCount(value);
1127 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001128 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001129 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001130
Guido van Rossum990f5c62000-05-04 15:07:16 +00001131 /* If the result contains any bytes with the top bit set,
1132 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001133#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001134 while (*p != '\0') {
1135 if (*p & 0x80)
1136 break;
1137 p++;
1138 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001139
Guido van Rossum990f5c62000-05-04 15:07:16 +00001140 if (*p == '\0')
1141 res = PyString_FromStringAndSize(s, (int)(p-s));
1142 else {
1143 /* Convert UTF-8 to Unicode string */
1144 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001145 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1146 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001147 PyErr_Clear();
1148 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001149 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001150 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001151#else
1152 p = strchr(p, '\0');
1153 res = PyString_FromStringAndSize(s, (int)(p-s));
1154#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001155 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001156 return res;
1157}
Guido van Rossum632de272000-03-29 00:19:50 +00001158
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001159/* Tkapp_CallProc is the event procedure that is executed in the context of
1160 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1161 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001162
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001163static int
1164Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1165{
1166 Tcl_Obj *objStore[ARGSZ];
1167 Tcl_Obj **objv;
1168 int objc;
1169 int i;
1170 ENTER_PYTHON
1171 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1172 if (!objv) {
1173 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1174 *(e->res) = NULL;
1175 }
1176 LEAVE_PYTHON
1177 if (!objv)
1178 goto done;
1179 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1180 ENTER_PYTHON
1181 if (i == TCL_ERROR) {
1182 *(e->res) = NULL;
1183 *(e->exc_type) = NULL;
1184 *(e->exc_tb) = NULL;
1185 *(e->exc_value) = PyObject_CallFunction(
1186 Tkinter_TclError, "s",
1187 Tcl_GetStringResult(e->self->interp));
1188 }
1189 else {
1190 *(e->res) = Tkapp_CallResult(e->self);
1191 }
1192 LEAVE_PYTHON
1193 done:
1194 /* Wake up calling thread. */
1195 Tcl_MutexLock(&call_mutex);
1196 Tcl_ConditionNotify(&e->done);
1197 Tcl_MutexUnlock(&call_mutex);
1198 return 1;
1199}
1200
1201/* This is the main entry point for calling a Tcl command.
1202 It supports three cases, with regard to threading:
1203 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1204 the context of the calling thread.
1205 2. Tcl is threaded, caller of the command is in the interpreter thread:
1206 Execute the command in the calling thread. Since the Tcl lock will
1207 not be used, we can merge that with case 1.
1208 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1209 the interpreter thread. Allocation of Tcl objects needs to occur in the
1210 interpreter thread, so we ship the PyObject* args to the target thread,
1211 and perform processing there. */
1212
1213static PyObject *
1214Tkapp_Call(PyObject *_self, PyObject *args)
1215{
1216 Tcl_Obj *objStore[ARGSZ];
1217 Tcl_Obj **objv = NULL;
1218 int objc, i;
1219 PyObject *res = NULL;
1220 TkappObject *self = (TkappObject*)_self;
1221 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1222 int flags = TCL_EVAL_DIRECT;
1223
1224 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1225 /* We cannot call the command directly. Instead, we must
1226 marshal the parameters to the interpreter thread. */
1227 Tkapp_CallEvent *ev;
1228 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001229 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001230 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001231 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1232 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1233 ev->self = self;
1234 ev->args = args;
1235 ev->res = &res;
1236 ev->exc_type = &exc_type;
1237 ev->exc_value = &exc_value;
1238 ev->exc_tb = &exc_tb;
1239 ev->done = (Tcl_Condition)0;
1240
1241 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1242
1243 if (res == NULL) {
1244 if (exc_type)
1245 PyErr_Restore(exc_type, exc_value, exc_tb);
1246 else
1247 PyErr_SetObject(Tkinter_TclError, exc_value);
1248 }
1249 }
1250 else {
1251
1252 objv = Tkapp_CallArgs(args, objStore, &objc);
1253 if (!objv)
1254 return NULL;
1255
1256 ENTER_TCL
1257
1258 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1259
1260 ENTER_OVERLAP
1261
1262 if (i == TCL_ERROR)
1263 Tkinter_Error(_self);
1264 else
1265 res = Tkapp_CallResult(self);
1266
1267 LEAVE_OVERLAP_TCL
1268
1269 Tkapp_CallDeallocArgs(objv, objStore, objc);
1270 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001271 return res;
1272}
1273
1274
1275static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001276Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001277{
Guido van Rossum212643f1998-04-29 16:22:14 +00001278 /* Could do the same here as for Tkapp_Call(), but this is not used
1279 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1280 way for the user to do what all its Global* variants do (save and
1281 reset the scope pointer, call the local version, restore the saved
1282 scope pointer). */
1283
Guido van Rossum62320c91998-06-15 04:36:09 +00001284 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001285 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001286
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001287 CHECK_TCL_APPARTMENT;
1288
Guido van Rossum62320c91998-06-15 04:36:09 +00001289 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001290 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001291 int err;
1292 ENTER_TCL
1293 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001294 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001295 if (err == TCL_ERROR)
1296 res = Tkinter_Error(self);
1297 else
1298 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001299 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001300 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001301 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001302
1303 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001304}
1305
1306static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001307Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001308{
Barry Warsawfa701a81997-01-16 00:15:11 +00001309 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001310 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001311 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001312
Guido van Rossum43713e52000-02-29 13:59:29 +00001313 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001314 return NULL;
1315
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001316 CHECK_TCL_APPARTMENT;
1317
Guido van Rossum00d93061998-05-28 23:06:38 +00001318 ENTER_TCL
1319 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001320 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001321 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001322 res = Tkinter_Error(self);
1323 else
1324 res = PyString_FromString(Tkapp_Result(self));
1325 LEAVE_OVERLAP_TCL
1326 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001327}
1328
1329static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001330Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001331{
Barry Warsawfa701a81997-01-16 00:15:11 +00001332 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001333 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001334 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001335
Guido van Rossum43713e52000-02-29 13:59:29 +00001336 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001337 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001338
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001339 CHECK_TCL_APPARTMENT;
1340
Guido van Rossum00d93061998-05-28 23:06:38 +00001341 ENTER_TCL
1342 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001343 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001344 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001345 res = Tkinter_Error(self);
1346 else
1347 res = PyString_FromString(Tkapp_Result(self));
1348 LEAVE_OVERLAP_TCL
1349 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001350}
1351
1352static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001353Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001354{
Barry Warsawfa701a81997-01-16 00:15:11 +00001355 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001356 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001357 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001358
Guido van Rossum43713e52000-02-29 13:59:29 +00001359 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001360 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001361
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001362 CHECK_TCL_APPARTMENT;
1363
Guido van Rossum00d93061998-05-28 23:06:38 +00001364 ENTER_TCL
1365 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001366 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001367 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001368 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001369
Guido van Rossum62320c91998-06-15 04:36:09 +00001370 else
1371 res = PyString_FromString(Tkapp_Result(self));
1372 LEAVE_OVERLAP_TCL
1373 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001374}
1375
1376static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001377Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001378{
Barry Warsawfa701a81997-01-16 00:15:11 +00001379 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001380 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001381 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001382
Guido van Rossum35d43371997-08-02 00:09:09 +00001383 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001384 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001385
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001386 CHECK_TCL_APPARTMENT;
1387
Guido van Rossum00d93061998-05-28 23:06:38 +00001388 ENTER_TCL
1389 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001390 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001391 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001392 res = Tkinter_Error(self);
1393 else
1394 res = PyString_FromString(Tkapp_Result(self));
1395 LEAVE_OVERLAP_TCL
1396 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001397}
1398
1399static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001400Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001401{
Barry Warsawfa701a81997-01-16 00:15:11 +00001402 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001403
Guido van Rossum43713e52000-02-29 13:59:29 +00001404 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001405 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001406 CHECK_TCL_APPARTMENT;
1407
Guido van Rossum00d93061998-05-28 23:06:38 +00001408 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001409 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001410 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001411
Barry Warsawfa701a81997-01-16 00:15:11 +00001412 Py_INCREF(Py_None);
1413 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001414}
1415
Barry Warsawfa701a81997-01-16 00:15:11 +00001416
1417
Guido van Rossum18468821994-06-20 07:49:28 +00001418/** Tcl Variable **/
1419
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001420TCL_DECLARE_MUTEX(var_mutex)
1421
Martin v. Löwis5b177f12002-12-30 18:14:15 +00001422typedef CONST84_RETURN char* (*EventFunc1)(Tcl_Interp*, CONST char*, int);
1423typedef CONST84_RETURN char* (*EventFunc2)(Tcl_Interp*, CONST char*, CONST char*, int);
1424typedef CONST84_RETURN char* (*EventFunc3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001425typedef struct VarEvent {
1426 Tcl_Event ev; /* must be first */
1427 TkappObject *self;
1428 char* arg1;
1429 char* arg2;
1430 char* arg3;
1431 int flags;
1432 EventFunc1 func1;
1433 EventFunc2 func2;
1434 EventFunc3 func3;
1435 PyObject **res;
1436 PyObject **exc;
1437 Tcl_Condition cond;
1438 int coderesult;
1439} VarEvent;
1440
1441static const char*
1442var_perform(VarEvent *ev)
1443{
1444 if (!ev->arg2 && !ev->arg2)
1445 return ev->func1(ev->self->interp, ev->arg1, ev->flags);
1446 if (!ev->arg3)
1447 return ev->func2(ev->self->interp, ev->arg1,
1448 ev->arg2, ev->flags);
1449 return ev->func3(ev->self->interp, ev->arg1, ev->arg2,
1450 ev->arg3, ev->flags);
1451}
1452
1453static void
1454var_fill_result(VarEvent *ev, const char* res)
1455{
1456 if (ev->coderesult) {
1457 if ((int)res != TCL_ERROR) {
1458 Py_INCREF(Py_None);
1459 *(ev->res) = Py_None;
1460 return;
1461 }
1462 }
1463 else if (res) {
1464 *(ev->res) = PyString_FromString(res);
1465 return;
1466 }
1467
1468 *(ev->res) = NULL;
1469 *(ev->exc) = PyObject_CallFunction(
1470 Tkinter_TclError, "s",
1471 Tcl_GetStringResult(ev->self->interp));
1472
1473}
1474
1475static int
1476var_proc(VarEvent* ev, int flags)
1477{
1478 const char *result = var_perform(ev);
1479 ENTER_PYTHON
1480 var_fill_result(ev, result);
1481 Tcl_MutexLock(&var_mutex);
1482 Tcl_ConditionNotify(&ev->cond);
1483 Tcl_MutexUnlock(&var_mutex);
1484 LEAVE_PYTHON
1485 return 1;
1486}
1487
1488static PyObject*
1489var_invoke(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
1490 EventFunc1 func1, EventFunc2 func2, EventFunc3 func3,
1491 int coderesult)
1492{
1493 VarEvent _ev;
1494 TkappObject *self = (TkappObject*)_self;
1495 VarEvent *ev = self->threaded ?
1496 (VarEvent*)ckalloc(sizeof(VarEvent)) : &_ev;
1497 PyObject *res, *exc;
1498
1499 ev->self = self;
1500 ev->arg1 = arg1;
1501 ev->arg2 = arg2;
1502 ev->arg3 = arg3;
1503 ev->flags = flags;
1504 ev->func1 = func1;
1505 ev->func2 = func2;
1506 ev->func3 = func3;
1507 ev->coderesult = coderesult;
1508 ev->res = &res;
1509 ev->exc = &exc;
1510 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1511 /* The current thread is not the interpreter thread. Marshal
1512 the call to the interpreter thread, then wait for
1513 completion. */
1514
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001515 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001516 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001517 ev->cond = NULL;
1518 ev->ev.proc = (Tcl_EventProc*)var_proc;
1519 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1520 }
1521 else {
1522 /* Tcl is not threaded, or this is the interpreter thread. To
1523 perform the call, we must hold the TCL lock. To receive the
1524 results, we must also hold the Python lock. */
1525 const char *result;
1526 ENTER_TCL
1527 result = var_perform(ev);
1528 ENTER_OVERLAP
1529 var_fill_result(ev, result);
1530 LEAVE_OVERLAP_TCL
1531 }
1532 if (!res) {
1533 PyErr_SetObject(Tkinter_TclError, exc);
1534 return NULL;
1535 }
1536 return res;
1537}
1538
1539static PyObject*
1540var_invoke2(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
Martin v. Löwis5b177f12002-12-30 18:14:15 +00001541 int (*func1)(Tcl_Interp*, CONST char*, int),
1542 int (*func2)(Tcl_Interp*, CONST char*, CONST char*, int),
1543 int (*func3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001544{
1545 return var_invoke(_self, arg1, arg2, arg3, flags,
1546 (EventFunc1)func1, (EventFunc2)func2,
1547 (EventFunc3)func3, 1);
1548}
1549
Guido van Rossum18468821994-06-20 07:49:28 +00001550static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001551SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001552{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001553 char *name1, *name2, *s;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001554 PyObject *res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001555 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +00001556 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +00001557
Guido van Rossum62320c91998-06-15 04:36:09 +00001558 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +00001559 if (!tmp)
1560 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001561
Guido van Rossum43713e52000-02-29 13:59:29 +00001562 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001563 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +00001564 s = AsString(newValue, tmp);
Guido van Rossum2834b972000-10-06 16:58:26 +00001565 if (s == NULL)
1566 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001567 res = var_invoke(self, name1, s, NULL, flags,
1568 NULL, Tcl_SetVar, NULL, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001569 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001570 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001571 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001572 if (PyArg_ParseTuple(args, "ssO:setvar",
1573 &name1, &name2, &newValue)) {
1574 s = AsString(newValue, tmp);
1575 if (s == NULL)
1576 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001577 res = var_invoke(self, name1, name2, s, flags,
1578 NULL, NULL, Tcl_SetVar2, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001579 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001580 else {
Guido van Rossum00d93061998-05-28 23:06:38 +00001581 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +00001582 return NULL;
1583 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001584 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001585 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +00001586
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001587 if (!res)
1588 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001589
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001590 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001591 Py_INCREF(Py_None);
1592 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001593}
1594
1595static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001596Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001597{
Barry Warsawfa701a81997-01-16 00:15:11 +00001598 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001599}
1600
1601static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001602Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001603{
Barry Warsawfa701a81997-01-16 00:15:11 +00001604 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001605}
1606
Barry Warsawfa701a81997-01-16 00:15:11 +00001607
1608
Guido van Rossum18468821994-06-20 07:49:28 +00001609static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001610GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001611{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001612 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001613 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001614
Guido van Rossum43713e52000-02-29 13:59:29 +00001615 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001616 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001617
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001618 res = var_invoke(self, name1, name2, NULL, flags,
1619 Tcl_GetVar, Tcl_GetVar2, NULL, 0);
Guido van Rossum62320c91998-06-15 04:36:09 +00001620 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001621}
1622
1623static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001624Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001625{
Barry Warsawfa701a81997-01-16 00:15:11 +00001626 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001627}
1628
1629static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001630Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001631{
Barry Warsawfa701a81997-01-16 00:15:11 +00001632 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001633}
1634
Barry Warsawfa701a81997-01-16 00:15:11 +00001635
1636
Guido van Rossum18468821994-06-20 07:49:28 +00001637static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001638UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001639{
Guido van Rossum35d43371997-08-02 00:09:09 +00001640 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001641 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001642
Guido van Rossum43713e52000-02-29 13:59:29 +00001643 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001644 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001645
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001646 res = var_invoke2(self, name1, name2, NULL, flags,
1647 Tcl_UnsetVar, Tcl_UnsetVar2, NULL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001648 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001649}
1650
1651static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001652Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001653{
Barry Warsawfa701a81997-01-16 00:15:11 +00001654 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001655}
1656
1657static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001658Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001659{
Barry Warsawfa701a81997-01-16 00:15:11 +00001660 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001661}
1662
Barry Warsawfa701a81997-01-16 00:15:11 +00001663
1664
Guido van Rossum18468821994-06-20 07:49:28 +00001665/** Tcl to Python **/
1666
1667static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001668Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001669{
Barry Warsawfa701a81997-01-16 00:15:11 +00001670 char *s;
1671 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001672
Martin v. Löwisffad6332002-11-26 09:28:05 +00001673 if (PyTuple_Size(args) == 1) {
1674 PyObject* o = PyTuple_GetItem(args, 0);
1675 if (PyInt_Check(o)) {
1676 Py_INCREF(o);
1677 return o;
1678 }
1679 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001680 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001681 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001682 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001683 return Tkinter_Error(self);
1684 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001685}
1686
1687static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001688Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001689{
Barry Warsawfa701a81997-01-16 00:15:11 +00001690 char *s;
1691 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001692
Martin v. Löwisffad6332002-11-26 09:28:05 +00001693 if (PyTuple_Size(args) == 1) {
1694 PyObject *o = PyTuple_GetItem(args, 0);
1695 if (PyFloat_Check(o)) {
1696 Py_INCREF(o);
1697 return o;
1698 }
1699 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001700 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001701 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001702 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001703 return Tkinter_Error(self);
1704 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001705}
1706
1707static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001708Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001709{
Barry Warsawfa701a81997-01-16 00:15:11 +00001710 char *s;
1711 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001712
Martin v. Löwisffad6332002-11-26 09:28:05 +00001713 if (PyTuple_Size(args) == 1) {
1714 PyObject *o = PyTuple_GetItem(args, 0);
1715 if (PyInt_Check(o)) {
1716 Py_INCREF(o);
1717 return o;
1718 }
1719 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001720 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001721 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001722 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1723 return Tkinter_Error(self);
Barry Warsawfa701a81997-01-16 00:15:11 +00001724 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001725}
1726
1727static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001728Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001729{
Barry Warsawfa701a81997-01-16 00:15:11 +00001730 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001731 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001732 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001733
Guido van Rossum43713e52000-02-29 13:59:29 +00001734 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001735 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001736
1737 CHECK_TCL_APPARTMENT;
1738
Guido van Rossum00d93061998-05-28 23:06:38 +00001739 ENTER_TCL
1740 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001741 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001742 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001743 res = Tkinter_Error(self);
1744 else
1745 res = Py_BuildValue("s", Tkapp_Result(self));
1746 LEAVE_OVERLAP_TCL
1747 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001748}
1749
1750static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001751Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001752{
Barry Warsawfa701a81997-01-16 00:15:11 +00001753 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001754 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001755 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001756 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001757
Guido van Rossum43713e52000-02-29 13:59:29 +00001758 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001759 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001760
1761 CHECK_TCL_APPARTMENT;
1762
Guido van Rossum00d93061998-05-28 23:06:38 +00001763 ENTER_TCL
1764 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001765 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001766 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001767 res = Tkinter_Error(self);
1768 else
1769 res = Py_BuildValue("l", v);
1770 LEAVE_OVERLAP_TCL
1771 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001772}
1773
1774static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001775Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001776{
Barry Warsawfa701a81997-01-16 00:15:11 +00001777 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001778 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001779 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001780 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001781
Guido van Rossum43713e52000-02-29 13:59:29 +00001782 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001783 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001784 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001785 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001786 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001787 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001788 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001789 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001790 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001791 res = Tkinter_Error(self);
1792 else
1793 res = Py_BuildValue("d", v);
1794 LEAVE_OVERLAP_TCL
1795 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001796}
1797
1798static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001799Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001800{
Barry Warsawfa701a81997-01-16 00:15:11 +00001801 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001802 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001803 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001804 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001805
Guido van Rossum43713e52000-02-29 13:59:29 +00001806 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001807 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001808 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001809 ENTER_TCL
1810 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001811 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001812 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001813 res = Tkinter_Error(self);
1814 else
1815 res = Py_BuildValue("i", v);
1816 LEAVE_OVERLAP_TCL
1817 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001818}
1819
Barry Warsawfa701a81997-01-16 00:15:11 +00001820
1821
Guido van Rossum18468821994-06-20 07:49:28 +00001822static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001823Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001824{
Barry Warsawfa701a81997-01-16 00:15:11 +00001825 char *list;
1826 int argc;
1827 char **argv;
1828 PyObject *v;
1829 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001830
Martin v. Löwisffad6332002-11-26 09:28:05 +00001831 if (PyTuple_Size(args) == 1) {
1832 v = PyTuple_GetItem(args, 0);
1833 if (PyTuple_Check(v)) {
1834 Py_INCREF(v);
1835 return v;
1836 }
1837 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001838 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001839 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001840
Barry Warsawfa701a81997-01-16 00:15:11 +00001841 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1842 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001843
Barry Warsawfa701a81997-01-16 00:15:11 +00001844 if (!(v = PyTuple_New(argc)))
1845 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001846
Barry Warsawfa701a81997-01-16 00:15:11 +00001847 for (i = 0; i < argc; i++) {
1848 PyObject *s = PyString_FromString(argv[i]);
1849 if (!s || PyTuple_SetItem(v, i, s)) {
1850 Py_DECREF(v);
1851 v = NULL;
1852 goto finally;
1853 }
1854 }
Guido van Rossum18468821994-06-20 07:49:28 +00001855
Barry Warsawfa701a81997-01-16 00:15:11 +00001856 finally:
1857 ckfree(FREECAST argv);
1858 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001859}
1860
1861static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001862Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001863{
Barry Warsawfa701a81997-01-16 00:15:11 +00001864 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001865
Martin v. Löwisffad6332002-11-26 09:28:05 +00001866 if (PyTuple_Size(args) == 1) {
1867 PyObject* o = PyTuple_GetItem(args, 0);
1868 if (PyTuple_Check(o)) {
1869 o = SplitObj(o);
1870 return o;
1871 }
1872 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001873 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001874 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001875 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001876}
1877
1878static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001879Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001880{
Barry Warsawfa701a81997-01-16 00:15:11 +00001881 char *s = Merge(args);
1882 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001883
Barry Warsawfa701a81997-01-16 00:15:11 +00001884 if (s) {
1885 res = PyString_FromString(s);
1886 ckfree(s);
1887 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001888
1889 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001890}
1891
Barry Warsawfa701a81997-01-16 00:15:11 +00001892
1893
Guido van Rossum18468821994-06-20 07:49:28 +00001894/** Tcl Command **/
1895
Guido van Rossum00d93061998-05-28 23:06:38 +00001896/* Client data struct */
1897typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001898 PyObject *self;
1899 PyObject *func;
1900} PythonCmd_ClientData;
1901
1902static int
Fred Drake509d79a2000-07-08 04:04:38 +00001903PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001904{
1905 errorInCmd = 1;
1906 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1907 LEAVE_PYTHON
1908 return TCL_ERROR;
1909}
1910
Guido van Rossum18468821994-06-20 07:49:28 +00001911/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001912 * function or method.
1913 */
Guido van Rossum18468821994-06-20 07:49:28 +00001914static int
Fred Drake509d79a2000-07-08 04:04:38 +00001915PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001916{
Guido van Rossum00d93061998-05-28 23:06:38 +00001917 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001918 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001919 int i, rv;
1920 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001921
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001922 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001923
Barry Warsawfa701a81997-01-16 00:15:11 +00001924 /* TBD: no error checking here since we know, via the
1925 * Tkapp_CreateCommand() that the client data is a two-tuple
1926 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001927 self = data->self;
1928 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001929
Barry Warsawfa701a81997-01-16 00:15:11 +00001930 /* Create argument list (argv1, ..., argvN) */
1931 if (!(arg = PyTuple_New(argc - 1)))
1932 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001933
Barry Warsawfa701a81997-01-16 00:15:11 +00001934 for (i = 0; i < (argc - 1); i++) {
1935 PyObject *s = PyString_FromString(argv[i + 1]);
1936 if (!s || PyTuple_SetItem(arg, i, s)) {
1937 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001938 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001939 }
1940 }
1941 res = PyEval_CallObject(func, arg);
1942 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001943
Barry Warsawfa701a81997-01-16 00:15:11 +00001944 if (res == NULL)
1945 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001946
Barry Warsawfa701a81997-01-16 00:15:11 +00001947 if (!(tmp = PyList_New(0))) {
1948 Py_DECREF(res);
1949 return PythonCmd_Error(interp);
1950 }
1951
Guido van Rossum2834b972000-10-06 16:58:26 +00001952 s = AsString(res, tmp);
1953 if (s == NULL) {
1954 rv = PythonCmd_Error(interp);
1955 }
1956 else {
1957 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1958 rv = TCL_OK;
1959 }
1960
Barry Warsawfa701a81997-01-16 00:15:11 +00001961 Py_DECREF(res);
1962 Py_DECREF(tmp);
1963
Guido van Rossum00d93061998-05-28 23:06:38 +00001964 LEAVE_PYTHON
1965
Guido van Rossum2834b972000-10-06 16:58:26 +00001966 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001967}
1968
1969static void
Fred Drake509d79a2000-07-08 04:04:38 +00001970PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001971{
Guido van Rossum00d93061998-05-28 23:06:38 +00001972 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1973
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001974 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001975 Py_XDECREF(data->self);
1976 Py_XDECREF(data->func);
1977 PyMem_DEL(data);
1978 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001979}
1980
Barry Warsawfa701a81997-01-16 00:15:11 +00001981
1982
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001983
1984TCL_DECLARE_MUTEX(command_mutex)
1985
1986typedef struct CommandEvent{
1987 Tcl_Event ev;
1988 Tcl_Interp* interp;
1989 char *name;
1990 int create;
1991 int *status;
1992 ClientData *data;
1993 Tcl_Condition done;
1994} CommandEvent;
1995
1996static int
1997Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001998{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001999 if (ev->create)
2000 *ev->status = Tcl_CreateCommand(
2001 ev->interp, ev->name, PythonCmd,
2002 ev->data, PythonCmdDelete) == NULL;
2003 else
2004 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2005 Tcl_MutexLock(&command_mutex);
2006 Tcl_ConditionNotify(&ev->done);
2007 Tcl_MutexUnlock(&command_mutex);
2008 return 1;
2009}
2010
2011static PyObject *
2012Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2013{
2014 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002015 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002016 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002017 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002018 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002019
Guido van Rossum43713e52000-02-29 13:59:29 +00002020 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002021 return NULL;
2022 if (!PyCallable_Check(func)) {
2023 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002024 return NULL;
2025 }
Guido van Rossum18468821994-06-20 07:49:28 +00002026
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002027 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002028 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002029 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002030
Guido van Rossum00d93061998-05-28 23:06:38 +00002031 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002032 if (!data)
2033 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002034 Py_XINCREF(self);
2035 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002036 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002037 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002038
2039 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2040 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2041 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2042 ev->interp = self->interp;
2043 ev->create = 1;
2044 ev->name = cmdName;
2045 ev->data = (ClientData)data;
2046 ev->status = &err;
2047 ev->done = NULL;
2048 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2049 }
2050 else {
2051 ENTER_TCL
2052 err = Tcl_CreateCommand(
2053 Tkapp_Interp(self), cmdName, PythonCmd,
2054 (ClientData)data, PythonCmdDelete) == NULL;
2055 LEAVE_TCL
2056 }
2057 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002058 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002059 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002060 return NULL;
2061 }
Guido van Rossum18468821994-06-20 07:49:28 +00002062
Barry Warsawfa701a81997-01-16 00:15:11 +00002063 Py_INCREF(Py_None);
2064 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002065}
2066
Barry Warsawfa701a81997-01-16 00:15:11 +00002067
2068
Guido van Rossum18468821994-06-20 07:49:28 +00002069static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002070Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002071{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002072 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002073 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002074 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002075
Guido van Rossum43713e52000-02-29 13:59:29 +00002076 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002077 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002078 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2079 CommandEvent *ev;
2080 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2081 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2082 ev->interp = self->interp;
2083 ev->create = 0;
2084 ev->name = cmdName;
2085 ev->status = &err;
2086 ev->done = NULL;
2087 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2088 &command_mutex);
2089 }
2090 else {
2091 ENTER_TCL
2092 err = Tcl_DeleteCommand(self->interp, cmdName);
2093 LEAVE_TCL
2094 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002095 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002096 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2097 return NULL;
2098 }
2099 Py_INCREF(Py_None);
2100 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002101}
2102
Barry Warsawfa701a81997-01-16 00:15:11 +00002103
2104
Guido van Rossum00d93061998-05-28 23:06:38 +00002105#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002106/** File Handler **/
2107
Guido van Rossum00d93061998-05-28 23:06:38 +00002108typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002109 PyObject *func;
2110 PyObject *file;
2111 int id;
2112 struct _fhcdata *next;
2113} FileHandler_ClientData;
2114
2115static FileHandler_ClientData *HeadFHCD;
2116
2117static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002118NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002119{
2120 FileHandler_ClientData *p;
2121 p = PyMem_NEW(FileHandler_ClientData, 1);
2122 if (p != NULL) {
2123 Py_XINCREF(func);
2124 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002125 p->func = func;
2126 p->file = file;
2127 p->id = id;
2128 p->next = HeadFHCD;
2129 HeadFHCD = p;
2130 }
2131 return p;
2132}
2133
2134static void
Fred Drake509d79a2000-07-08 04:04:38 +00002135DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002136{
2137 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002138
2139 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002140 while ((p = *pp) != NULL) {
2141 if (p->id == id) {
2142 *pp = p->next;
2143 Py_XDECREF(p->func);
2144 Py_XDECREF(p->file);
2145 PyMem_DEL(p);
2146 }
2147 else
2148 pp = &p->next;
2149 }
2150}
2151
Guido van Rossuma597dde1995-01-10 20:56:29 +00002152static void
Fred Drake509d79a2000-07-08 04:04:38 +00002153FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002154{
Guido van Rossum00d93061998-05-28 23:06:38 +00002155 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002156 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002157
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002158 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002159 func = data->func;
2160 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002161
Barry Warsawfa701a81997-01-16 00:15:11 +00002162 arg = Py_BuildValue("(Oi)", file, (long) mask);
2163 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002164 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002165
2166 if (res == NULL) {
2167 errorInCmd = 1;
2168 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2169 }
2170 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002171 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002172}
2173
Guido van Rossum18468821994-06-20 07:49:28 +00002174static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002175Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2176 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002177{
Guido van Rossum00d93061998-05-28 23:06:38 +00002178 FileHandler_ClientData *data;
2179 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002180 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002181
Guido van Rossum2834b972000-10-06 16:58:26 +00002182 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2183 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002184 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002185 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002186 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002187 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002188 return NULL;
2189 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002190 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002191 return NULL;
2192 }
2193
Guido van Rossuma80649b2000-03-28 20:07:05 +00002194 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002195 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002196 return NULL;
2197
Barry Warsawfa701a81997-01-16 00:15:11 +00002198 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002199 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002200 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002201 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002202 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002203 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002204}
2205
2206static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002207Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002208{
Barry Warsawfa701a81997-01-16 00:15:11 +00002209 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002210 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002211
Guido van Rossum43713e52000-02-29 13:59:29 +00002212 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002213 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002214 CHECK_TCL_APPARTMENT;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002215 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002216 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002217 return NULL;
2218
Guido van Rossuma80649b2000-03-28 20:07:05 +00002219 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002220
Barry Warsawfa701a81997-01-16 00:15:11 +00002221 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002222 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002223 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002224 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002225 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002226 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002227}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002228#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002229
Barry Warsawfa701a81997-01-16 00:15:11 +00002230
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002231/**** Tktt Object (timer token) ****/
2232
Jeremy Hylton938ace62002-07-17 16:30:39 +00002233static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002234
Guido van Rossum00d93061998-05-28 23:06:38 +00002235typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002236 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002237 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002238 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002239} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002240
2241static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002242Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002243{
Barry Warsawfa701a81997-01-16 00:15:11 +00002244 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002245 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002246
Guido van Rossum43713e52000-02-29 13:59:29 +00002247 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002248 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002249 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002250 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002251 v->token = NULL;
2252 }
2253 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002254 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002255 Py_DECREF(func);
2256 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002257 }
2258 Py_INCREF(Py_None);
2259 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002260}
2261
2262static PyMethodDef Tktt_methods[] =
2263{
Neal Norwitzb0493252002-03-31 14:44:22 +00002264 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002265 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002266};
2267
2268static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002269Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002270{
Barry Warsawfa701a81997-01-16 00:15:11 +00002271 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002272
Guido van Rossumb18618d2000-05-03 23:44:39 +00002273 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002274 if (v == NULL)
2275 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002276
Guido van Rossum00d93061998-05-28 23:06:38 +00002277 Py_INCREF(func);
2278 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002279 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002280
2281 /* Extra reference, deleted when called or when handler is deleted */
2282 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002283 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002284}
2285
2286static void
Fred Drake509d79a2000-07-08 04:04:38 +00002287Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002288{
Guido van Rossum00d93061998-05-28 23:06:38 +00002289 TkttObject *v = (TkttObject *)self;
2290 PyObject *func = v->func;
2291
2292 Py_XDECREF(func);
2293
Guido van Rossumb18618d2000-05-03 23:44:39 +00002294 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002295}
2296
Guido van Rossum597ac201998-05-12 14:36:19 +00002297static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002298Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002299{
Barry Warsawfa701a81997-01-16 00:15:11 +00002300 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002301 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002302
Tim Peters885d4572001-11-28 20:27:42 +00002303 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002304 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002305 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002306}
2307
2308static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002309Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002310{
Barry Warsawfa701a81997-01-16 00:15:11 +00002311 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002312}
2313
2314static PyTypeObject Tktt_Type =
2315{
Guido van Rossum35d43371997-08-02 00:09:09 +00002316 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002317 0, /*ob_size */
2318 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002319 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002320 0, /*tp_itemsize */
2321 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002322 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002323 Tktt_GetAttr, /*tp_getattr */
2324 0, /*tp_setattr */
2325 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002326 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002327 0, /*tp_as_number */
2328 0, /*tp_as_sequence */
2329 0, /*tp_as_mapping */
2330 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002331};
2332
Barry Warsawfa701a81997-01-16 00:15:11 +00002333
2334
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002335/** Timer Handler **/
2336
2337static void
Fred Drake509d79a2000-07-08 04:04:38 +00002338TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002339{
Guido van Rossum00d93061998-05-28 23:06:38 +00002340 TkttObject *v = (TkttObject *)clientData;
2341 PyObject *func = v->func;
2342 PyObject *res;
2343
2344 if (func == NULL)
2345 return;
2346
2347 v->func = NULL;
2348
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002349 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002350
2351 res = PyEval_CallObject(func, NULL);
2352 Py_DECREF(func);
2353 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002354
Barry Warsawfa701a81997-01-16 00:15:11 +00002355 if (res == NULL) {
2356 errorInCmd = 1;
2357 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2358 }
2359 else
2360 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002361
2362 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002363}
2364
2365static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002366Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002367{
Barry Warsawfa701a81997-01-16 00:15:11 +00002368 int milliseconds;
2369 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002370 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002371
Guido van Rossum2834b972000-10-06 16:58:26 +00002372 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2373 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002374 return NULL;
2375 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002376 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002377 return NULL;
2378 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002379 v = Tktt_New(func);
2380 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2381 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002382
Guido van Rossum00d93061998-05-28 23:06:38 +00002383 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002384}
2385
Barry Warsawfa701a81997-01-16 00:15:11 +00002386
Guido van Rossum18468821994-06-20 07:49:28 +00002387/** Event Loop **/
2388
Guido van Rossum18468821994-06-20 07:49:28 +00002389static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002390Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002391{
Barry Warsawfa701a81997-01-16 00:15:11 +00002392 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002393 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002394#ifdef WITH_THREAD
2395 PyThreadState *tstate = PyThreadState_Get();
2396#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002397
Guido van Rossum43713e52000-02-29 13:59:29 +00002398 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002399 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002400
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002401 CHECK_TCL_APPARTMENT;
2402
Barry Warsawfa701a81997-01-16 00:15:11 +00002403 quitMainLoop = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002404 self->dispatching = 1;
Barry Warsawfa701a81997-01-16 00:15:11 +00002405 while (Tk_GetNumMainWindows() > threshold &&
2406 !quitMainLoop &&
2407 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002408 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002409 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002410
2411#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002412 if (self->threaded) {
2413 /* Allow other Python threads to run. */
2414 ENTER_TCL
2415 result = Tcl_DoOneEvent(0);
2416 LEAVE_TCL
2417 }
2418 else {
2419 Py_BEGIN_ALLOW_THREADS
2420 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2421 tcl_tstate = tstate;
2422 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2423 tcl_tstate = NULL;
2424 if(tcl_lock)PyThread_release_lock(tcl_lock);
2425 if (result == 0)
2426 Sleep(20);
2427 Py_END_ALLOW_THREADS
2428 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002429#else
2430 result = Tcl_DoOneEvent(0);
2431#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002432
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002433 if (PyErr_CheckSignals() != 0) {
2434 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002435 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002436 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002437 if (result < 0)
2438 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002439 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002440 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002441 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002442
Barry Warsawfa701a81997-01-16 00:15:11 +00002443 if (errorInCmd) {
2444 errorInCmd = 0;
2445 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2446 excInCmd = valInCmd = trbInCmd = NULL;
2447 return NULL;
2448 }
2449 Py_INCREF(Py_None);
2450 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002451}
2452
2453static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002454Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002455{
Guido van Rossum35d43371997-08-02 00:09:09 +00002456 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002457 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002458
Guido van Rossum43713e52000-02-29 13:59:29 +00002459 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002460 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002461 CHECK_TCL_APPARTMENT;
Barry Warsawfa701a81997-01-16 00:15:11 +00002462
Guido van Rossum00d93061998-05-28 23:06:38 +00002463 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002464 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002465 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002466 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002467}
2468
2469static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002470Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002471{
2472
Guido van Rossum43713e52000-02-29 13:59:29 +00002473 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002474 return NULL;
2475
2476 quitMainLoop = 1;
2477 Py_INCREF(Py_None);
2478 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002479}
2480
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002481static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002482Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002483{
2484
Guido van Rossum43713e52000-02-29 13:59:29 +00002485 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002486 return NULL;
2487
2488 return PyInt_FromLong((long)Tkapp_Interp(self));
2489}
2490
Barry Warsawfa701a81997-01-16 00:15:11 +00002491
Martin v. Löwisffad6332002-11-26 09:28:05 +00002492static PyObject *
2493Tkapp_WantObjects(PyObject *self, PyObject *args)
2494{
2495
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002496 int wantobjects;
2497 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002498 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002499 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002500
2501 Py_INCREF(Py_None);
2502 return Py_None;
2503}
2504
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002505static PyObject *
2506Tkapp_WillDispatch(PyObject *self, PyObject *args)
2507{
2508
2509 ((TkappObject*)self)->dispatching = 1;
2510
2511 Py_INCREF(Py_None);
2512 return Py_None;
2513}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002514
Barry Warsawfa701a81997-01-16 00:15:11 +00002515
Guido van Rossum18468821994-06-20 07:49:28 +00002516/**** Tkapp Method List ****/
2517
2518static PyMethodDef Tkapp_methods[] =
2519{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002520 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002521 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002522 {"call", Tkapp_Call, METH_OLDARGS},
2523 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2524 {"eval", Tkapp_Eval, METH_VARARGS},
2525 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2526 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2527 {"record", Tkapp_Record, METH_VARARGS},
2528 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2529 {"setvar", Tkapp_SetVar, METH_VARARGS},
2530 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2531 {"getvar", Tkapp_GetVar, METH_VARARGS},
2532 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2533 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2534 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2535 {"getint", Tkapp_GetInt, METH_VARARGS},
2536 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2537 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2538 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2539 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2540 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2541 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2542 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2543 {"split", Tkapp_Split, METH_VARARGS},
2544 {"merge", Tkapp_Merge, METH_OLDARGS},
2545 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2546 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002547#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002548 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2549 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002550#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002551 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2552 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2553 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2554 {"quit", Tkapp_Quit, METH_VARARGS},
2555 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002556 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002557};
2558
Barry Warsawfa701a81997-01-16 00:15:11 +00002559
2560
Guido van Rossum18468821994-06-20 07:49:28 +00002561/**** Tkapp Type Methods ****/
2562
2563static void
Fred Drake509d79a2000-07-08 04:04:38 +00002564Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002565{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002566 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002567 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002568 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002569 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002570 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002571 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002572}
2573
2574static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002575Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002576{
Guido van Rossum35d43371997-08-02 00:09:09 +00002577 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002578}
2579
2580static PyTypeObject Tkapp_Type =
2581{
Guido van Rossum35d43371997-08-02 00:09:09 +00002582 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002583 0, /*ob_size */
2584 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002585 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002586 0, /*tp_itemsize */
2587 Tkapp_Dealloc, /*tp_dealloc */
2588 0, /*tp_print */
2589 Tkapp_GetAttr, /*tp_getattr */
2590 0, /*tp_setattr */
2591 0, /*tp_compare */
2592 0, /*tp_repr */
2593 0, /*tp_as_number */
2594 0, /*tp_as_sequence */
2595 0, /*tp_as_mapping */
2596 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002597};
2598
Barry Warsawfa701a81997-01-16 00:15:11 +00002599
2600
Guido van Rossum18468821994-06-20 07:49:28 +00002601/**** Tkinter Module ****/
2602
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002603typedef struct {
2604 PyObject* tuple;
2605 int size; /* current size */
2606 int maxsize; /* allocated size */
2607} FlattenContext;
2608
2609static int
2610_bump(FlattenContext* context, int size)
2611{
Guido van Rossum2834b972000-10-06 16:58:26 +00002612 /* expand tuple to hold (at least) size new items.
2613 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002614
2615 int maxsize = context->maxsize * 2;
2616
2617 if (maxsize < context->size + size)
2618 maxsize = context->size + size;
2619
2620 context->maxsize = maxsize;
2621
Tim Peters4324aa32001-05-28 22:30:08 +00002622 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002623}
2624
2625static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002626_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002627{
2628 /* add tuple or list to argument tuple (recursively) */
2629
2630 int i, size;
2631
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002632 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002633 PyErr_SetString(PyExc_ValueError,
2634 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002635 return 0;
2636 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002637 size = PyList_GET_SIZE(item);
2638 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002639 if (context->size + size > context->maxsize &&
2640 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002641 return 0;
2642 /* copy items to output tuple */
2643 for (i = 0; i < size; i++) {
2644 PyObject *o = PyList_GET_ITEM(item, i);
2645 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002646 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002647 return 0;
2648 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002649 if (context->size + 1 > context->maxsize &&
2650 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002651 return 0;
2652 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002653 PyTuple_SET_ITEM(context->tuple,
2654 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002655 }
2656 }
2657 } else if (PyTuple_Check(item)) {
2658 /* same, for tuples */
2659 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002660 if (context->size + size > context->maxsize &&
2661 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002662 return 0;
2663 for (i = 0; i < size; i++) {
2664 PyObject *o = PyTuple_GET_ITEM(item, i);
2665 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002666 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002667 return 0;
2668 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002669 if (context->size + 1 > context->maxsize &&
2670 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002671 return 0;
2672 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002673 PyTuple_SET_ITEM(context->tuple,
2674 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002675 }
2676 }
2677 } else {
2678 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2679 return 0;
2680 }
2681 return 1;
2682}
2683
2684static PyObject *
2685Tkinter_Flatten(PyObject* self, PyObject* args)
2686{
2687 FlattenContext context;
2688 PyObject* item;
2689
2690 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2691 return NULL;
2692
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002693 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002694 if (context.maxsize <= 0)
2695 return PyTuple_New(0);
2696
2697 context.tuple = PyTuple_New(context.maxsize);
2698 if (!context.tuple)
2699 return NULL;
2700
2701 context.size = 0;
2702
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002703 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002704 return NULL;
2705
Tim Peters4324aa32001-05-28 22:30:08 +00002706 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002707 return NULL;
2708
2709 return context.tuple;
2710}
2711
Guido van Rossum18468821994-06-20 07:49:28 +00002712static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002713Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002714{
Barry Warsawfa701a81997-01-16 00:15:11 +00002715 char *screenName = NULL;
2716 char *baseName = NULL;
2717 char *className = NULL;
2718 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002719 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002720
Guido van Rossum35d43371997-08-02 00:09:09 +00002721 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002722 if (baseName != NULL)
2723 baseName++;
2724 else
2725 baseName = Py_GetProgramName();
2726 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002727
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002728 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002729 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002730 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002731 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002732
Barry Warsawfa701a81997-01-16 00:15:11 +00002733 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002734 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002735}
2736
2737static PyMethodDef moduleMethods[] =
2738{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002739 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2740 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002741#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002742 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2743 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002744#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002745 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2746 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2747 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2748 {"quit", Tkapp_Quit, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002749 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002750};
2751
Guido van Rossum7bf15641998-05-22 18:28:17 +00002752#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002753
2754static int stdin_ready = 0;
2755
Guido van Rossumad4db171998-06-13 13:56:28 +00002756#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002757static void
Fred Drake509d79a2000-07-08 04:04:38 +00002758MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002759{
2760 stdin_ready = 1;
2761}
Guido van Rossumad4db171998-06-13 13:56:28 +00002762#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002763
Guido van Rossum00d93061998-05-28 23:06:38 +00002764static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002765
Guido van Rossum18468821994-06-20 07:49:28 +00002766static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002767EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002768{
Guido van Rossumad4db171998-06-13 13:56:28 +00002769#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002770 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002771#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002772#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002773 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002774#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002775 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002776 errorInCmd = 0;
2777#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002778 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002779 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002780#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002781 while (!errorInCmd && !stdin_ready) {
2782 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002783#ifdef MS_WINDOWS
2784 if (_kbhit()) {
2785 stdin_ready = 1;
2786 break;
2787 }
2788#endif
2789#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002790 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002791 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002792 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002793
Guido van Rossum00d93061998-05-28 23:06:38 +00002794 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002795
2796 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002797 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002798 if (result == 0)
2799 Sleep(20);
2800 Py_END_ALLOW_THREADS
2801#else
2802 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002803#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002804
2805 if (result < 0)
2806 break;
2807 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002808#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002809 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002810#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002811 if (errorInCmd) {
2812 errorInCmd = 0;
2813 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2814 excInCmd = valInCmd = trbInCmd = NULL;
2815 PyErr_Print();
2816 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002817#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002818 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002819#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002820 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002821}
Guido van Rossum18468821994-06-20 07:49:28 +00002822
Guido van Rossum00d93061998-05-28 23:06:38 +00002823#endif
2824
Guido van Rossum7bf15641998-05-22 18:28:17 +00002825static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002826EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002827{
Guido van Rossum00d93061998-05-28 23:06:38 +00002828#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002829 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002830#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002831 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002832#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002833 PyOS_InputHook = EventHook;
2834 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002835#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002836}
2837
2838static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002839DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002840{
Guido van Rossum00d93061998-05-28 23:06:38 +00002841#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002842 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2843 PyOS_InputHook = NULL;
2844 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002845#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002846}
2847
Barry Warsawfa701a81997-01-16 00:15:11 +00002848
2849/* all errors will be checked in one fell swoop in init_tkinter() */
2850static void
Fred Drake509d79a2000-07-08 04:04:38 +00002851ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002852{
2853 PyObject *v = PyInt_FromLong(val);
2854 if (v) {
2855 PyDict_SetItemString(d, name, v);
2856 Py_DECREF(v);
2857 }
2858}
2859static void
Fred Drake509d79a2000-07-08 04:04:38 +00002860ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002861{
2862 PyObject *v = PyString_FromString(val);
2863 if (v) {
2864 PyDict_SetItemString(d, name, v);
2865 Py_DECREF(v);
2866 }
2867}
2868
2869
Mark Hammond62b1ab12002-07-23 06:31:15 +00002870PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002871init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002872{
Barry Warsawfa701a81997-01-16 00:15:11 +00002873 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002874
Barry Warsawfa701a81997-01-16 00:15:11 +00002875 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002876
2877#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002878 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002879#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002880
Barry Warsawfa701a81997-01-16 00:15:11 +00002881 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002882
Barry Warsawfa701a81997-01-16 00:15:11 +00002883 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00002884 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00002885 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002886
Guido van Rossum35d43371997-08-02 00:09:09 +00002887 ins_long(d, "READABLE", TCL_READABLE);
2888 ins_long(d, "WRITABLE", TCL_WRITABLE);
2889 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2890 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2891 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2892 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2893 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2894 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2895 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002896 ins_string(d, "TK_VERSION", TK_VERSION);
2897 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002898
Guido van Rossum83551bf1997-09-13 00:44:23 +00002899 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002900
2901 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002902 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2903
Martin v. Löwisffad6332002-11-26 09:28:05 +00002904 PyTclObject_Type.ob_type = &PyType_Type;
Jason Tishlerbbe89612002-12-31 20:30:46 +00002905 PyTclObject_Type.tp_getattro = &PyObject_GenericGetAttr;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002906 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002907
2908#ifdef TK_AQUA
2909 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2910 * start waking up. Note that Tcl_FindExecutable will do this, this
2911 * code must be above it! The original warning from
2912 * tkMacOSXAppInit.c is copied below.
2913 *
2914 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2915 * Tcl interpreter for now. It probably should work to do this
2916 * in the other order, but for now it doesn't seem to.
2917 *
2918 */
2919 Tk_MacOSXSetupTkNotifier();
2920#endif
2921
2922
Guido van Rossume187b0e2000-03-27 21:46:29 +00002923 /* This helps the dynamic loader; in Unicode aware Tcl versions
2924 it also helps Tcl find its encodings. */
2925 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00002926
Barry Warsawfa701a81997-01-16 00:15:11 +00002927 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002928 return;
2929
Guido van Rossum43ff8681998-07-14 18:02:13 +00002930#if 0
2931 /* This was not a good idea; through <Destroy> bindings,
2932 Tcl_Finalize() may invoke Python code but at that point the
2933 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002934 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002935#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002936
Jack Jansen34cc5c31995-10-31 16:15:12 +00002937#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002938 /*
2939 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2940 ** Most of the initializations in that routine (toolbox init calls and
2941 ** such) have already been done for us, so we only need these.
2942 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002943 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002944
2945 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00002946#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00002947 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00002948#endif /* GENERATINGCFM */
2949#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00002950}
Guido van Rossum9722ad81995-09-22 23:49:28 +00002951
Guido van Rossumec22c921996-02-25 04:50:29 +00002952
Barry Warsawfa701a81997-01-16 00:15:11 +00002953
Guido van Rossum9722ad81995-09-22 23:49:28 +00002954#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002955
2956/*
Guido van Rossumec22c921996-02-25 04:50:29 +00002957** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002958*/
2959
Guido van Rossum9722ad81995-09-22 23:49:28 +00002960void
2961panic(char * format, ...)
2962{
Barry Warsawfa701a81997-01-16 00:15:11 +00002963 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002964
Barry Warsawfa701a81997-01-16 00:15:11 +00002965 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002966
Guido van Rossum227cf761998-08-05 13:53:32 +00002967 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002968 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002969
Barry Warsawfa701a81997-01-16 00:15:11 +00002970 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002971
Barry Warsawfa701a81997-01-16 00:15:11 +00002972 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00002973}
Jack Jansen40b546d1995-11-14 10:34:45 +00002974
Guido van Rossumec22c921996-02-25 04:50:29 +00002975/*
2976** Pass events to SIOUX before passing them to Tk.
2977*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002978
Guido van Rossumec22c921996-02-25 04:50:29 +00002979static int
Fred Drake509d79a2000-07-08 04:04:38 +00002980PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002981{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002982 WindowPtr frontwin;
2983 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00002984 ** Sioux eats too many events, so we don't pass it everything. We
2985 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002986 ** the Sioux window is frontmost. This means that Tk menus don't work
2987 ** in that case, but at least we can scroll the sioux window.
2988 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2989 ** part of the external interface of Sioux...
2990 */
2991 frontwin = FrontWindow();
2992 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
2993 if (SIOUXHandleOneEvent(eventPtr))
2994 return 0; /* Nothing happened to the Tcl event queue */
2995 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002996 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002997}
2998
Guido van Rossumec22c921996-02-25 04:50:29 +00002999#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003000
3001/*
3002** Additional Mac specific code for dealing with shared libraries.
3003*/
3004
3005#include <Resources.h>
3006#include <CodeFragments.h>
3007
3008static int loaded_from_shlib = 0;
3009static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003010
Jack Jansen34cc5c31995-10-31 16:15:12 +00003011/*
3012** If this module is dynamically loaded the following routine should
3013** be the init routine. It takes care of adding the shared library to
3014** the resource-file chain, so that the tk routines can find their
3015** resources.
3016*/
3017OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003018init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003019{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00003020 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00003021 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003022 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003023 library_fss = *data->fragLocator.u.onDisk.fileSpec;
3024 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003025 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003026 library_fss = *data->fragLocator.u.inSegs.fileSpec;
3027 loaded_from_shlib = 1;
3028 }
3029 return noErr;
3030}
3031
3032/*
3033** Insert the library resources into the search path. Put them after
3034** the resources from the application. Again, we ignore errors.
3035*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003036static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003037mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003038{
3039 if ( !loaded_from_shlib )
3040 return;
3041 (void)FSpOpenResFile(&library_fss, fsRdPerm);
3042}
3043
Guido van Rossumec22c921996-02-25 04:50:29 +00003044#endif /* GENERATINGCFM */
3045#endif /* macintosh */