blob: 0fb1228a27dc3c9d0935a20c019844cafb627b08 [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
3Copyright 1994-1995 by Stichting Mathematisch Centrum, Amsterdam,
4The Netherlands.
5
6 All Rights Reserved
7
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00008Copyright (c) 2000, BeOpen.com.
9Copyright (c) 1995-2000, Corporation for National Research Initiatives.
10Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
11All rights reserved.
Guido van Rossum845547d1996-06-26 18:26:04 +000012
Guido van Rossumfd71b9e2000-06-30 23:50:40 +000013See the file "Misc/COPYRIGHT" for information on usage and
14redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossum845547d1996-06-26 18:26:04 +000015
16******************************************************************/
17
18/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +000019
Guido van Rossum7ffa7611996-08-13 21:10:16 +000020/* TCL/TK VERSION INFO:
21
Guido van Rossuma80649b2000-03-28 20:07:05 +000022 Only Tcl/Tk 8.0 and later are supported. Older versions are not
23 supported. (Use Python 1.5.2 if you cannot upgrade your Tcl/Tk
24 libraries.)
25*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000026
Guido van Rossuma80649b2000-03-28 20:07:05 +000027/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000028
29 - In Tcl_Call(), create Tcl objects from the arguments, possibly using
30 intelligent mappings between Python objects and Tcl objects (e.g. ints,
31 floats and Tcl window pointers could be handled specially).
32
33 - Register a new Tcl type, "Python callable", which can be called more
34 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
35
Guido van Rossum7ffa7611996-08-13 21:10:16 +000036*/
37
Guido van Rossum35d43371997-08-02 00:09:09 +000038
Guido van Rossum9722ad81995-09-22 23:49:28 +000039#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000040#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000041
Guido van Rossum00d93061998-05-28 23:06:38 +000042#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000043#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000044#endif
45
Guido van Rossum2a5119b1998-05-29 01:28:40 +000046#ifdef MS_WINDOWS
47#include <windows.h>
48#endif
49
Guido van Rossumbf0dc9f1996-08-20 20:49:56 +000050#ifdef macintosh
51#define MAC_TCL
Guido van Rossum290283b1997-06-02 22:16:43 +000052#include "myselect.h"
Guido van Rossumbf0dc9f1996-08-20 20:49:56 +000053#endif
54
Guido van Rossum49b56061998-10-01 20:42:43 +000055#ifdef PYOS_OS2
56#include "myselect.h"
57#endif
58
Guido van Rossum18468821994-06-20 07:49:28 +000059#include <tcl.h>
60#include <tk.h>
61
Guido van Rossum3e819a71997-08-01 19:29:02 +000062#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
63
Guido van Rossuma80649b2000-03-28 20:07:05 +000064#if TKMAJORMINOR < 8000
65#error "Tk older than 8.0 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000066#endif
67
Guido van Rossuma80649b2000-03-28 20:07:05 +000068#if defined(macintosh)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000069/* Sigh, we have to include this to get at the tcl qd pointer */
70#include <tkMac.h>
Guido van Rossum2ea1c941998-04-28 16:12:43 +000071/* And this one we need to clear the menu bar */
72#include <Menus.h>
Guido van Rossum0d2390c1997-08-14 19:57:07 +000073#endif
74
Guido van Rossuma80649b2000-03-28 20:07:05 +000075#if !defined(MS_WINDOWS)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000076#define HAVE_CREATEFILEHANDLER
77#endif
78
Guido van Rossum00d93061998-05-28 23:06:38 +000079#ifdef HAVE_CREATEFILEHANDLER
80
81/* Tcl_CreateFileHandler() changed several times; these macros deal with the
82 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
83 Unix, only because Jack added it back); when available on Windows, it only
84 applies to sockets. */
85
Guido van Rossum7bf15641998-05-22 18:28:17 +000086#ifdef MS_WINDOWS
87#define FHANDLETYPE TCL_WIN_SOCKET
88#else
89#define FHANDLETYPE TCL_UNIX_FD
90#endif
91
Guido van Rossum00d93061998-05-28 23:06:38 +000092/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
93 which uses this to handle Tcl events while the user is typing commands. */
94
95#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +000096#define WAIT_FOR_STDIN
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#endif /* HAVE_CREATEFILEHANDLER */
100
Guido van Rossumad4db171998-06-13 13:56:28 +0000101#ifdef MS_WINDOWS
102#include <conio.h>
103#define WAIT_FOR_STDIN
104#endif
105
Guido van Rossum00d93061998-05-28 23:06:38 +0000106#ifdef WITH_THREAD
107
108/* The threading situation is complicated. Tcl is not thread-safe, except for
109 Tcl 8.1, which will probably remain in alpha status for another 6 months
110 (and the README says that Tk will probably remain thread-unsafe forever).
111 So we need to use a lock around all uses of Tcl. Previously, the Python
112 interpreter lock was used for this. However, this causes problems when
113 other Python threads need to run while Tcl is blocked waiting for events.
114
115 To solve this problem, a separate lock for Tcl is introduced. Holding it
116 is incompatible with holding Python's interpreter lock. The following four
117 macros manipulate both locks together.
118
119 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
120 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
121 that could call an event handler, or otherwise affect the state of a Tcl
122 interpreter. These assume that the surrounding code has the Python
123 interpreter lock; inside the brackets, the Python interpreter lock has been
124 released and the lock for Tcl has been acquired.
125
Guido van Rossum5e977831998-06-15 14:03:52 +0000126 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
127 (For example, when transferring data from the Tcl interpreter result to a
128 Python string object.) This can be done by using different macros to close
129 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
130 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
131 releases the Tcl lock.
132
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000133 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000134 handlers when the handler needs to use Python. Such event handlers are
135 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000136 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000137 the Python interpreter lock, restoring the appropriate thread state, and
138 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
139 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000140 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000141
142 These locks expand to several statements and brackets; they should not be
143 used in branches of if statements and the like.
144
145*/
146
Guido van Rossum65d5b571998-12-21 19:32:43 +0000147static PyThread_type_lock tcl_lock = 0;
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000148static PyThreadState *tcl_tstate = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000149
150#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000151 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000152 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000153
154#define LEAVE_TCL \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000155 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000156
Guido van Rossum62320c91998-06-15 04:36:09 +0000157#define ENTER_OVERLAP \
158 Py_END_ALLOW_THREADS
159
160#define LEAVE_OVERLAP_TCL \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000161 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000162
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000163#define ENTER_PYTHON \
164 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000165 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000166
167#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000168 { PyThreadState *tstate = PyEval_SaveThread(); \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000169 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Guido van Rossum00d93061998-05-28 23:06:38 +0000170
171#else
172
173#define ENTER_TCL
174#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000175#define ENTER_OVERLAP
176#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000177#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000178#define LEAVE_PYTHON
179
180#endif
181
Guido van Rossumec22c921996-02-25 04:50:29 +0000182#ifdef macintosh
183
184/*
185** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000186** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000187*/
188
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000189/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000190#define FREECAST (char *)
191
Guido van Rossumec22c921996-02-25 04:50:29 +0000192#include <Events.h> /* For EventRecord */
193
Fred Drake509d79a2000-07-08 04:04:38 +0000194typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
195void Tcl_MacSetEventProc (TclMacConvertEventPtr procPtr);
196int TkMacConvertEvent (EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000197
Fred Drake509d79a2000-07-08 04:04:38 +0000198staticforward int PyMacConvertEvent (EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000199
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000200#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
201 #pragma import on
202#endif
203
204#include <SIOUX.h>
205extern int SIOUXIsAppWindow(WindowPtr);
206
207#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
208 #pragma import reset
209#endif
Guido van Rossumec22c921996-02-25 04:50:29 +0000210#endif /* macintosh */
211
Guido van Rossum97867b21996-08-08 19:09:53 +0000212#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000213#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000214#endif
215
Guido van Rossum18468821994-06-20 07:49:28 +0000216/**** Tkapp Object Declaration ****/
217
218staticforward PyTypeObject Tkapp_Type;
219
Guido van Rossum00d93061998-05-28 23:06:38 +0000220typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000221 PyObject_HEAD
222 Tcl_Interp *interp;
Guido van Rossum00d93061998-05-28 23:06:38 +0000223} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000224
225#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000226#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
227#define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
228
Guido van Rossum35d43371997-08-02 00:09:09 +0000229#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000230(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000231
Barry Warsawfa701a81997-01-16 00:15:11 +0000232
233
Guido van Rossum18468821994-06-20 07:49:28 +0000234/**** Error Handling ****/
235
236static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000237static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000238static int errorInCmd = 0;
239static PyObject *excInCmd;
240static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000241static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000242
Barry Warsawfa701a81997-01-16 00:15:11 +0000243
244
Guido van Rossum18468821994-06-20 07:49:28 +0000245static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000246Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000247{
Barry Warsawfa701a81997-01-16 00:15:11 +0000248 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
249 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000250}
251
Barry Warsawfa701a81997-01-16 00:15:11 +0000252
Barry Warsawfa701a81997-01-16 00:15:11 +0000253
Guido van Rossum18468821994-06-20 07:49:28 +0000254/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000255
256#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000257#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000258#include "mytime.h"
Guido van Rossum11801851999-01-25 21:39:03 +0000259#include "myselect.h"
Guido van Rossum541f2411998-08-13 13:29:22 +0000260
Guido van Rossum00d93061998-05-28 23:06:38 +0000261/* Millisecond sleep() for Unix platforms. */
262
263static void
Fred Drake509d79a2000-07-08 04:04:38 +0000264Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000265{
266 /* XXX Too bad if you don't have select(). */
267 struct timeval t;
268 double frac;
269 t.tv_sec = milli/1000;
270 t.tv_usec = (milli%1000) * 1000;
271 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
272}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000273#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000274#endif /* WITH_THREAD */
275
276
Guido van Rossum18468821994-06-20 07:49:28 +0000277static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000278AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000279{
Guido van Rossum35d43371997-08-02 00:09:09 +0000280 if (PyString_Check(value))
281 return PyString_AsString(value);
Barry Warsawfa701a81997-01-16 00:15:11 +0000282 else {
283 PyObject *v = PyObject_Str(value);
284 PyList_Append(tmp, v);
285 Py_DECREF(v);
286 return PyString_AsString(v);
287 }
Guido van Rossum18468821994-06-20 07:49:28 +0000288}
289
Barry Warsawfa701a81997-01-16 00:15:11 +0000290
291
Guido van Rossum18468821994-06-20 07:49:28 +0000292#define ARGSZ 64
293
294static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000295Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000296{
Barry Warsawfa701a81997-01-16 00:15:11 +0000297 PyObject *tmp = NULL;
298 char *argvStore[ARGSZ];
299 char **argv = NULL;
300 int fvStore[ARGSZ];
301 int *fv = NULL;
302 int argc = 0, i;
303 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000304
Barry Warsawfa701a81997-01-16 00:15:11 +0000305 if (!(tmp = PyList_New(0)))
306 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000307
Barry Warsawfa701a81997-01-16 00:15:11 +0000308 argv = argvStore;
309 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000310
Barry Warsawfa701a81997-01-16 00:15:11 +0000311 if (args == NULL)
312 argc = 0;
313
314 else if (!PyTuple_Check(args)) {
315 argc = 1;
316 fv[0] = 0;
317 argv[0] = AsString(args, tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000318 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000319 else {
320 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000321
Barry Warsawfa701a81997-01-16 00:15:11 +0000322 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000323 argv = (char **)ckalloc(argc * sizeof(char *));
324 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000325 if (argv == NULL || fv == NULL) {
326 PyErr_NoMemory();
327 goto finally;
328 }
329 }
330
331 for (i = 0; i < argc; i++) {
332 PyObject *v = PyTuple_GetItem(args, i);
333 if (PyTuple_Check(v)) {
334 fv[i] = 1;
335 if (!(argv[i] = Merge(v)))
336 goto finally;
337 }
338 else if (v == Py_None) {
339 argc = i;
340 break;
341 }
342 else {
343 fv[i] = 0;
344 argv[i] = AsString(v, tmp);
345 }
346 }
Guido van Rossum18468821994-06-20 07:49:28 +0000347 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000348 res = Tcl_Merge(argc, argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000349
Barry Warsawfa701a81997-01-16 00:15:11 +0000350 finally:
351 for (i = 0; i < argc; i++)
352 if (fv[i]) {
353 ckfree(argv[i]);
354 }
355 if (argv != argvStore)
356 ckfree(FREECAST argv);
357 if (fv != fvStore)
358 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000359
Barry Warsawfa701a81997-01-16 00:15:11 +0000360 Py_DECREF(tmp);
361 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000362}
363
Barry Warsawfa701a81997-01-16 00:15:11 +0000364
365
Guido van Rossum18468821994-06-20 07:49:28 +0000366static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000367Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000368{
Barry Warsawfa701a81997-01-16 00:15:11 +0000369 int argc;
370 char **argv;
371 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000372
Barry Warsawfa701a81997-01-16 00:15:11 +0000373 if (list == NULL) {
374 Py_INCREF(Py_None);
375 return Py_None;
376 }
Guido van Rossum18468821994-06-20 07:49:28 +0000377
Guido van Rossum00d93061998-05-28 23:06:38 +0000378 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000379 /* Not a list.
380 * Could be a quoted string containing funnies, e.g. {"}.
381 * Return the string itself.
382 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000383 return PyString_FromString(list);
384 }
Guido van Rossum18468821994-06-20 07:49:28 +0000385
Barry Warsawfa701a81997-01-16 00:15:11 +0000386 if (argc == 0)
387 v = PyString_FromString("");
388 else if (argc == 1)
389 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000390 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000391 int i;
392 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000393
Barry Warsawfa701a81997-01-16 00:15:11 +0000394 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000395 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000396 Py_DECREF(v);
397 v = NULL;
398 break;
399 }
400 PyTuple_SetItem(v, i, w);
401 }
402 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000403 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000404 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000405}
406
Barry Warsawfa701a81997-01-16 00:15:11 +0000407
408
Guido van Rossum18468821994-06-20 07:49:28 +0000409/**** Tkapp Object ****/
410
411#ifndef WITH_APPINIT
412int
Fred Drake509d79a2000-07-08 04:04:38 +0000413Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000414{
Barry Warsawfa701a81997-01-16 00:15:11 +0000415 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000416
Barry Warsawfa701a81997-01-16 00:15:11 +0000417 main = Tk_MainWindow(interp);
418 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000419 PySys_WriteStderr("Tcl_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000420 return TCL_ERROR;
421 }
422 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000423 PySys_WriteStderr("Tk_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000424 return TCL_ERROR;
425 }
426 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000427}
428#endif /* !WITH_APPINIT */
429
Guido van Rossum18468821994-06-20 07:49:28 +0000430
Barry Warsawfa701a81997-01-16 00:15:11 +0000431
432
433/* Initialize the Tk application; see the `main' function in
434 * `tkMain.c'.
435 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000436
437static void EnableEventHook(); /* Forward */
438static void DisableEventHook(); /* Forward */
439
Barry Warsawfa701a81997-01-16 00:15:11 +0000440static TkappObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000441Tkapp_New(char *screenName, char *baseName, char *className, int interactive)
Barry Warsawfa701a81997-01-16 00:15:11 +0000442{
443 TkappObject *v;
444 char *argv0;
445
Guido van Rossumb18618d2000-05-03 23:44:39 +0000446 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000447 if (v == NULL)
448 return NULL;
449
450 v->interp = Tcl_CreateInterp();
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000451
Guido van Rossuma80649b2000-03-28 20:07:05 +0000452#if defined(macintosh)
453 /* This seems to be needed */
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000454 ClearMenuBar();
455 TkMacInitMenus(v->interp);
456#endif
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000457 /* Delete the 'exit' command, which can screw things up */
458 Tcl_DeleteCommand(v->interp, "exit");
459
Barry Warsawfa701a81997-01-16 00:15:11 +0000460 if (screenName != NULL)
461 Tcl_SetVar2(v->interp, "env", "DISPLAY",
462 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000463
Barry Warsawfa701a81997-01-16 00:15:11 +0000464 if (interactive)
465 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
466 else
467 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000468
Barry Warsawfa701a81997-01-16 00:15:11 +0000469 /* This is used to get the application class for Tk 4.1 and up */
470 argv0 = (char*)ckalloc(strlen(className) + 1);
471 if (!argv0) {
472 PyErr_NoMemory();
473 Py_DECREF(v);
474 return NULL;
475 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000476
Barry Warsawfa701a81997-01-16 00:15:11 +0000477 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000478 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000479 argv0[0] = tolower(argv0[0]);
480 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
481 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000482
Barry Warsawfa701a81997-01-16 00:15:11 +0000483 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000484 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000485
Guido van Rossum7bf15641998-05-22 18:28:17 +0000486 EnableEventHook();
487
Barry Warsawfa701a81997-01-16 00:15:11 +0000488 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000489}
490
Barry Warsawfa701a81997-01-16 00:15:11 +0000491
492
Guido van Rossum18468821994-06-20 07:49:28 +0000493/** Tcl Eval **/
494
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000495#if TKMAJORMINOR >= 8001
496#define USING_OBJECTS
497#endif
498
499#ifdef USING_OBJECTS
500
501static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000502AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000503{
504 Tcl_Obj *result;
505
506 if (PyString_Check(value))
507 return Tcl_NewStringObj(PyString_AS_STRING(value),
508 PyString_GET_SIZE(value));
509 else if (PyInt_Check(value))
510 return Tcl_NewLongObj(PyInt_AS_LONG(value));
511 else if (PyFloat_Check(value))
512 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
513 else if (PyTuple_Check(value)) {
514 Tcl_Obj **argv = (Tcl_Obj**)
515 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
516 int i;
517 if(!argv)
518 return 0;
519 for(i=0;i<PyTuple_Size(value);i++)
520 argv[i] = AsObj(PyTuple_GetItem(value,i));
521 result = Tcl_NewListObj(PyTuple_Size(value), argv);
522 ckfree(FREECAST argv);
523 return result;
524 }
525 else if (PyUnicode_Check(value)) {
Guido van Rossum990f5c62000-05-04 15:07:16 +0000526#if TKMAJORMINOR <= 8001
527 /* In Tcl 8.1 we must use UTF-8 */
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000528 PyObject* utf8 = PyUnicode_AsUTF8String (value);
529 if (!utf8)
530 return 0;
Guido van Rossum8823acc2000-04-27 20:14:31 +0000531 result = Tcl_NewStringObj (PyString_AS_STRING (utf8),
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000532 PyString_GET_SIZE (utf8));
Guido van Rossum8823acc2000-04-27 20:14:31 +0000533 Py_DECREF(utf8);
534 return result;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000535#else /* TKMAJORMINOR > 8001 */
536 /* In Tcl 8.2 and later, use Tcl_NewUnicodeObj() */
537 if (sizeof(Py_UNICODE) != sizeof(Tcl_UniChar)) {
538 /* XXX Should really test this at compile time */
539 PyErr_SetString(PyExc_SystemError,
540 "Py_UNICODE and Tcl_UniChar differ in size");
541 return 0;
542 }
543 return Tcl_NewUnicodeObj(PyUnicode_AS_UNICODE(value),
544 PyUnicode_GET_SIZE(value));
545#endif /* TKMAJORMINOR > 8001 */
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000546 }
547 else {
548 PyObject *v = PyObject_Str(value);
549 if (!v)
550 return 0;
551 result = AsObj(v);
552 Py_DECREF(v);
553 return result;
554 }
555}
556
Guido van Rossum18468821994-06-20 07:49:28 +0000557static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000558Tkapp_Call(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000559{
Guido van Rossum632de272000-03-29 00:19:50 +0000560 Tcl_Obj *objStore[ARGSZ];
561 Tcl_Obj **objv = NULL;
562 int objc = 0, i;
563 PyObject *res = NULL;
564 Tcl_Interp *interp = Tkapp_Interp(self);
565 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
566 int flags = TCL_EVAL_DIRECT;
Guido van Rossum18468821994-06-20 07:49:28 +0000567
Guido van Rossum632de272000-03-29 00:19:50 +0000568 objv = objStore;
Barry Warsawfa701a81997-01-16 00:15:11 +0000569
Guido van Rossum212643f1998-04-29 16:22:14 +0000570 if (args == NULL)
Guido van Rossum632de272000-03-29 00:19:50 +0000571 objc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000572
Guido van Rossum212643f1998-04-29 16:22:14 +0000573 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +0000574 objc = 1;
575 objv[0] = AsObj(args);
576 if (objv[0] == 0)
577 goto finally;
578 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +0000579 }
580 else {
Guido van Rossum632de272000-03-29 00:19:50 +0000581 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +0000582
Guido van Rossum632de272000-03-29 00:19:50 +0000583 if (objc > ARGSZ) {
584 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
585 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +0000586 PyErr_NoMemory();
587 goto finally;
588 }
589 }
590
Guido van Rossum632de272000-03-29 00:19:50 +0000591 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +0000592 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +0000593 if (v == Py_None) {
594 objc = i;
595 break;
596 }
Guido van Rossum632de272000-03-29 00:19:50 +0000597 objv[i] = AsObj(v);
598 if (!objv[i])
599 goto finally;
600 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +0000601 }
602 }
Guido van Rossum212643f1998-04-29 16:22:14 +0000603
Guido van Rossum62320c91998-06-15 04:36:09 +0000604 ENTER_TCL
Guido van Rossum632de272000-03-29 00:19:50 +0000605
606 i = Tcl_EvalObjv(interp, objc, objv, flags);
607
Guido van Rossum62320c91998-06-15 04:36:09 +0000608 ENTER_OVERLAP
Guido van Rossum632de272000-03-29 00:19:50 +0000609 if (i == TCL_ERROR)
Guido van Rossum212643f1998-04-29 16:22:14 +0000610 Tkinter_Error(self);
Guido van Rossum990f5c62000-05-04 15:07:16 +0000611 else {
Guido van Rossum632de272000-03-29 00:19:50 +0000612 /* We could request the object result here, but doing
613 so would confuse applications that expect a string. */
Guido van Rossum990f5c62000-05-04 15:07:16 +0000614 char *s = Tcl_GetStringResult(interp);
615 char *p = s;
616 /* If the result contains any bytes with the top bit set,
617 it's UTF-8 and we should decode it to Unicode */
618 while (*p != '\0') {
619 if (*p & 0x80)
620 break;
621 p++;
622 }
623 if (*p == '\0')
624 res = PyString_FromStringAndSize(s, (int)(p-s));
625 else {
626 /* Convert UTF-8 to Unicode string */
627 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +0000628 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
629 if (res == NULL) {
630 PyErr_Clear();
631 res = PyString_FromStringAndSize(s, (int)(p-s));
632 }
Guido van Rossum990f5c62000-05-04 15:07:16 +0000633 }
634 }
Guido van Rossum632de272000-03-29 00:19:50 +0000635
Guido van Rossum62320c91998-06-15 04:36:09 +0000636 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000637
Guido van Rossum212643f1998-04-29 16:22:14 +0000638 finally:
Guido van Rossum632de272000-03-29 00:19:50 +0000639 for (i = 0; i < objc; i++)
640 Tcl_DecrRefCount(objv[i]);
641 if (objv != objStore)
642 ckfree(FREECAST objv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000643 return res;
644}
645
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000646#else /* !USING_OBJECTS */
647
648static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000649Tkapp_Call(PyObject *self, PyObject *args)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000650{
651 /* This is copied from Merge() */
652 PyObject *tmp = NULL;
653 char *argvStore[ARGSZ];
654 char **argv = NULL;
655 int fvStore[ARGSZ];
656 int *fv = NULL;
657 int argc = 0, i;
658 PyObject *res = NULL; /* except this has a different type */
659 Tcl_CmdInfo info; /* and this is added */
660 Tcl_Interp *interp = Tkapp_Interp(self); /* and this too */
661
662 if (!(tmp = PyList_New(0)))
663 return NULL;
664
665 argv = argvStore;
666 fv = fvStore;
667
668 if (args == NULL)
669 argc = 0;
670
671 else if (!PyTuple_Check(args)) {
672 argc = 1;
673 fv[0] = 0;
674 argv[0] = AsString(args, tmp);
675 }
676 else {
677 argc = PyTuple_Size(args);
678
679 if (argc > ARGSZ) {
680 argv = (char **)ckalloc(argc * sizeof(char *));
681 fv = (int *)ckalloc(argc * sizeof(int));
682 if (argv == NULL || fv == NULL) {
683 PyErr_NoMemory();
684 goto finally;
685 }
686 }
687
688 for (i = 0; i < argc; i++) {
689 PyObject *v = PyTuple_GetItem(args, i);
690 if (PyTuple_Check(v)) {
691 fv[i] = 1;
692 if (!(argv[i] = Merge(v)))
693 goto finally;
694 }
695 else if (v == Py_None) {
696 argc = i;
697 break;
698 }
699 else {
700 fv[i] = 0;
701 argv[i] = AsString(v, tmp);
702 }
703 }
704 }
705 /* End code copied from Merge() */
706
707 /* All this to avoid a call to Tcl_Merge() and the corresponding call
708 to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
709 if (Py_VerboseFlag >= 2) {
710 for (i = 0; i < argc; i++)
711 PySys_WriteStderr("%s ", argv[i]);
712 }
713 ENTER_TCL
714 info.proc = NULL;
715 if (argc < 1 ||
716 !Tcl_GetCommandInfo(interp, argv[0], &info) ||
717 info.proc == NULL)
718 {
719 char *cmd;
720 cmd = Tcl_Merge(argc, argv);
721 i = Tcl_Eval(interp, cmd);
722 ckfree(cmd);
723 }
724 else {
725 Tcl_ResetResult(interp);
726 i = (*info.proc)(info.clientData, interp, argc, argv);
727 }
728 ENTER_OVERLAP
729 if (info.proc == NULL && Py_VerboseFlag >= 2)
730 PySys_WriteStderr("... use TclEval ");
731 if (i == TCL_ERROR) {
732 if (Py_VerboseFlag >= 2)
733 PySys_WriteStderr("... error: '%s'\n",
734 interp->result);
735 Tkinter_Error(self);
736 }
737 else {
738 if (Py_VerboseFlag >= 2)
739 PySys_WriteStderr("-> '%s'\n", interp->result);
740 res = PyString_FromString(interp->result);
741 }
742 LEAVE_OVERLAP_TCL
743
744 /* Copied from Merge() again */
745 finally:
746 for (i = 0; i < argc; i++)
747 if (fv[i]) {
748 ckfree(argv[i]);
749 }
750 if (argv != argvStore)
751 ckfree(FREECAST argv);
752 if (fv != fvStore)
753 ckfree(FREECAST fv);
754
755 Py_DECREF(tmp);
756 return res;
757}
758
759#endif /* !USING_OBJECTS */
Barry Warsawfa701a81997-01-16 00:15:11 +0000760
761static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000762Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000763{
Guido van Rossum212643f1998-04-29 16:22:14 +0000764 /* Could do the same here as for Tkapp_Call(), but this is not used
765 much, so I can't be bothered. Unfortunately Tcl doesn't export a
766 way for the user to do what all its Global* variants do (save and
767 reset the scope pointer, call the local version, restore the saved
768 scope pointer). */
769
Guido van Rossum62320c91998-06-15 04:36:09 +0000770 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +0000771 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000772
Guido van Rossum62320c91998-06-15 04:36:09 +0000773 cmd = Merge(args);
Barry Warsawfa701a81997-01-16 00:15:11 +0000774 if (!cmd)
775 PyErr_SetString(Tkinter_TclError, "merge failed");
776
Guido van Rossum00d93061998-05-28 23:06:38 +0000777 else {
778 int err;
779 ENTER_TCL
780 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +0000781 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000782 if (err == TCL_ERROR)
783 res = Tkinter_Error(self);
784 else
785 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +0000786 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +0000787 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000788
789 if (cmd)
790 ckfree(cmd);
791
792 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000793}
794
795static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000796Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000797{
Barry Warsawfa701a81997-01-16 00:15:11 +0000798 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000799 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000800 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000801
Guido van Rossum43713e52000-02-29 13:59:29 +0000802 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000803 return NULL;
804
Guido van Rossum00d93061998-05-28 23:06:38 +0000805 ENTER_TCL
806 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000807 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000808 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000809 res = Tkinter_Error(self);
810 else
811 res = PyString_FromString(Tkapp_Result(self));
812 LEAVE_OVERLAP_TCL
813 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000814}
815
816static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000817Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000818{
Barry Warsawfa701a81997-01-16 00:15:11 +0000819 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000820 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000821 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +0000822
Guido van Rossum43713e52000-02-29 13:59:29 +0000823 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000824 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000825
Guido van Rossum00d93061998-05-28 23:06:38 +0000826 ENTER_TCL
827 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000828 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000829 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000830 res = Tkinter_Error(self);
831 else
832 res = PyString_FromString(Tkapp_Result(self));
833 LEAVE_OVERLAP_TCL
834 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000835}
836
837static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000838Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000839{
Barry Warsawfa701a81997-01-16 00:15:11 +0000840 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +0000841 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000842 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000843
Guido van Rossum43713e52000-02-29 13:59:29 +0000844 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +0000845 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000846
Guido van Rossum00d93061998-05-28 23:06:38 +0000847 ENTER_TCL
848 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +0000849 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000850 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000851 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +0000852
Guido van Rossum62320c91998-06-15 04:36:09 +0000853 else
854 res = PyString_FromString(Tkapp_Result(self));
855 LEAVE_OVERLAP_TCL
856 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000857}
858
859static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000860Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000861{
Barry Warsawfa701a81997-01-16 00:15:11 +0000862 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000863 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000864 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000865
Guido van Rossum35d43371997-08-02 00:09:09 +0000866 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000867 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000868
Guido van Rossum00d93061998-05-28 23:06:38 +0000869 ENTER_TCL
870 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +0000871 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000872 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000873 res = Tkinter_Error(self);
874 else
875 res = PyString_FromString(Tkapp_Result(self));
876 LEAVE_OVERLAP_TCL
877 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000878}
879
880static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000881Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000882{
Barry Warsawfa701a81997-01-16 00:15:11 +0000883 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +0000884
Guido van Rossum43713e52000-02-29 13:59:29 +0000885 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +0000886 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000887 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000888 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +0000889 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +0000890
Barry Warsawfa701a81997-01-16 00:15:11 +0000891 Py_INCREF(Py_None);
892 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000893}
894
Barry Warsawfa701a81997-01-16 00:15:11 +0000895
896
Guido van Rossum18468821994-06-20 07:49:28 +0000897/** Tcl Variable **/
898
899static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000900SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +0000901{
Guido van Rossum00d93061998-05-28 23:06:38 +0000902 char *name1, *name2, *ok, *s;
Barry Warsawfa701a81997-01-16 00:15:11 +0000903 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +0000904 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +0000905
Guido van Rossum62320c91998-06-15 04:36:09 +0000906 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +0000907 if (!tmp)
908 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000909
Guido van Rossum43713e52000-02-29 13:59:29 +0000910 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000911 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +0000912 s = AsString(newValue, tmp);
913 ENTER_TCL
914 ok = Tcl_SetVar(Tkapp_Interp(self), name1, s, flags);
915 LEAVE_TCL
916 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000917 else {
Guido van Rossum35d43371997-08-02 00:09:09 +0000918 PyErr_Clear();
Guido van Rossum43713e52000-02-29 13:59:29 +0000919 if (PyArg_ParseTuple(args, "ssO:setvar", &name1, &name2, &newValue)) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000920 s = AsString (newValue, tmp);
921 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000922 ok = Tcl_SetVar2(Tkapp_Interp(self), name1, name2,
Guido van Rossum00d93061998-05-28 23:06:38 +0000923 s, flags);
924 LEAVE_TCL
925 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000926 else {
Guido van Rossum00d93061998-05-28 23:06:38 +0000927 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +0000928 return NULL;
929 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000930 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000931 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000932
Barry Warsawfa701a81997-01-16 00:15:11 +0000933 if (!ok)
934 return Tkinter_Error(self);
935
936 Py_INCREF(Py_None);
937 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000938}
939
940static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000941Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000942{
Barry Warsawfa701a81997-01-16 00:15:11 +0000943 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000944}
945
946static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000947Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000948{
Barry Warsawfa701a81997-01-16 00:15:11 +0000949 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000950}
951
Barry Warsawfa701a81997-01-16 00:15:11 +0000952
953
Guido van Rossum18468821994-06-20 07:49:28 +0000954static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000955GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +0000956{
Guido van Rossum35d43371997-08-02 00:09:09 +0000957 char *name1, *name2=NULL, *s;
Guido van Rossum62320c91998-06-15 04:36:09 +0000958 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000959
Guido van Rossum43713e52000-02-29 13:59:29 +0000960 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +0000961 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000962 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000963 if (name2 == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000964 s = Tcl_GetVar(Tkapp_Interp(self), name1, flags);
Guido van Rossum18468821994-06-20 07:49:28 +0000965
Barry Warsawfa701a81997-01-16 00:15:11 +0000966 else
Guido van Rossum35d43371997-08-02 00:09:09 +0000967 s = Tcl_GetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +0000968 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +0000969
Barry Warsawfa701a81997-01-16 00:15:11 +0000970 if (s == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000971 res = Tkinter_Error(self);
972 else
973 res = PyString_FromString(s);
974 LEAVE_OVERLAP_TCL
975 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000976}
977
978static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000979Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000980{
Barry Warsawfa701a81997-01-16 00:15:11 +0000981 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000982}
983
984static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000985Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000986{
Barry Warsawfa701a81997-01-16 00:15:11 +0000987 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000988}
989
Barry Warsawfa701a81997-01-16 00:15:11 +0000990
991
Guido van Rossum18468821994-06-20 07:49:28 +0000992static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000993UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +0000994{
Guido van Rossum35d43371997-08-02 00:09:09 +0000995 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +0000996 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000997 int code;
Guido van Rossum18468821994-06-20 07:49:28 +0000998
Guido van Rossum43713e52000-02-29 13:59:29 +0000999 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001000 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001001 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001002 if (name2 == NULL)
1003 code = Tcl_UnsetVar(Tkapp_Interp(self), name1, flags);
1004
1005 else
1006 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +00001007 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +00001008
Barry Warsawfa701a81997-01-16 00:15:11 +00001009 if (code == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001010 res = Tkinter_Error(self);
1011 else {
1012 Py_INCREF(Py_None);
1013 res = Py_None;
1014 }
1015 LEAVE_OVERLAP_TCL
1016 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001017}
1018
1019static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001020Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001021{
Barry Warsawfa701a81997-01-16 00:15:11 +00001022 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001023}
1024
1025static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001026Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001027{
Barry Warsawfa701a81997-01-16 00:15:11 +00001028 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001029}
1030
Barry Warsawfa701a81997-01-16 00:15:11 +00001031
1032
Guido van Rossum18468821994-06-20 07:49:28 +00001033/** Tcl to Python **/
1034
1035static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001036Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001037{
Barry Warsawfa701a81997-01-16 00:15:11 +00001038 char *s;
1039 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001040
Guido van Rossum43713e52000-02-29 13:59:29 +00001041 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001042 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001043 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001044 return Tkinter_Error(self);
1045 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001046}
1047
1048static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001049Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001050{
Barry Warsawfa701a81997-01-16 00:15:11 +00001051 char *s;
1052 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001053
Guido van Rossum43713e52000-02-29 13:59:29 +00001054 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001055 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001056 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001057 return Tkinter_Error(self);
1058 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001059}
1060
1061static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001062Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001063{
Barry Warsawfa701a81997-01-16 00:15:11 +00001064 char *s;
1065 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001066
Guido van Rossum43713e52000-02-29 13:59:29 +00001067 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001068 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001069 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1070 return Tkinter_Error(self);
Barry Warsawfa701a81997-01-16 00:15:11 +00001071 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001072}
1073
1074static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001075Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001076{
Barry Warsawfa701a81997-01-16 00:15:11 +00001077 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001078 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001079 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001080
Guido van Rossum43713e52000-02-29 13:59:29 +00001081 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001082 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001083 ENTER_TCL
1084 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001085 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001086 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001087 res = Tkinter_Error(self);
1088 else
1089 res = Py_BuildValue("s", Tkapp_Result(self));
1090 LEAVE_OVERLAP_TCL
1091 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001092}
1093
1094static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001095Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001096{
Barry Warsawfa701a81997-01-16 00:15:11 +00001097 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001098 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001099 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001100 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001101
Guido van Rossum43713e52000-02-29 13:59:29 +00001102 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001103 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001104 ENTER_TCL
1105 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001106 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001107 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001108 res = Tkinter_Error(self);
1109 else
1110 res = Py_BuildValue("l", v);
1111 LEAVE_OVERLAP_TCL
1112 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001113}
1114
1115static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001116Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001117{
Barry Warsawfa701a81997-01-16 00:15:11 +00001118 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001119 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001120 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001121 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001122
Guido van Rossum43713e52000-02-29 13:59:29 +00001123 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001124 return NULL;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001125 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001126 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001127 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001128 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001129 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001130 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001131 res = Tkinter_Error(self);
1132 else
1133 res = Py_BuildValue("d", v);
1134 LEAVE_OVERLAP_TCL
1135 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001136}
1137
1138static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001139Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001140{
Barry Warsawfa701a81997-01-16 00:15:11 +00001141 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001142 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001143 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001144 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001145
Guido van Rossum43713e52000-02-29 13:59:29 +00001146 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001147 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001148 ENTER_TCL
1149 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001150 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001151 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001152 res = Tkinter_Error(self);
1153 else
1154 res = Py_BuildValue("i", v);
1155 LEAVE_OVERLAP_TCL
1156 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001157}
1158
Barry Warsawfa701a81997-01-16 00:15:11 +00001159
1160
Guido van Rossum18468821994-06-20 07:49:28 +00001161static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001162Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001163{
Barry Warsawfa701a81997-01-16 00:15:11 +00001164 char *list;
1165 int argc;
1166 char **argv;
1167 PyObject *v;
1168 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001169
Guido van Rossum43713e52000-02-29 13:59:29 +00001170 if (!PyArg_ParseTuple(args, "s:splitlist", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001171 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001172
Barry Warsawfa701a81997-01-16 00:15:11 +00001173 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1174 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001175
Barry Warsawfa701a81997-01-16 00:15:11 +00001176 if (!(v = PyTuple_New(argc)))
1177 return NULL;
1178
1179 for (i = 0; i < argc; i++) {
1180 PyObject *s = PyString_FromString(argv[i]);
1181 if (!s || PyTuple_SetItem(v, i, s)) {
1182 Py_DECREF(v);
1183 v = NULL;
1184 goto finally;
1185 }
1186 }
Guido van Rossum18468821994-06-20 07:49:28 +00001187
Barry Warsawfa701a81997-01-16 00:15:11 +00001188 finally:
1189 ckfree(FREECAST argv);
1190 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001191}
1192
1193static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001194Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001195{
Barry Warsawfa701a81997-01-16 00:15:11 +00001196 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001197
Guido van Rossum43713e52000-02-29 13:59:29 +00001198 if (!PyArg_ParseTuple(args, "s:split", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001199 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001200 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001201}
1202
1203static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001204Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001205{
Barry Warsawfa701a81997-01-16 00:15:11 +00001206 char *s = Merge(args);
1207 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001208
Barry Warsawfa701a81997-01-16 00:15:11 +00001209 if (s) {
1210 res = PyString_FromString(s);
1211 ckfree(s);
1212 }
1213 else
1214 PyErr_SetString(Tkinter_TclError, "merge failed");
1215
1216 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001217}
1218
Barry Warsawfa701a81997-01-16 00:15:11 +00001219
1220
Guido van Rossum18468821994-06-20 07:49:28 +00001221/** Tcl Command **/
1222
Guido van Rossum00d93061998-05-28 23:06:38 +00001223/* Client data struct */
1224typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001225 PyObject *self;
1226 PyObject *func;
1227} PythonCmd_ClientData;
1228
1229static int
Fred Drake509d79a2000-07-08 04:04:38 +00001230PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001231{
1232 errorInCmd = 1;
1233 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1234 LEAVE_PYTHON
1235 return TCL_ERROR;
1236}
1237
Guido van Rossum18468821994-06-20 07:49:28 +00001238/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001239 * function or method.
1240 */
Guido van Rossum18468821994-06-20 07:49:28 +00001241static int
Fred Drake509d79a2000-07-08 04:04:38 +00001242PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001243{
Guido van Rossum00d93061998-05-28 23:06:38 +00001244 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001245 PyObject *self, *func, *arg, *res, *tmp;
1246 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001247
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001248 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001249
Barry Warsawfa701a81997-01-16 00:15:11 +00001250 /* TBD: no error checking here since we know, via the
1251 * Tkapp_CreateCommand() that the client data is a two-tuple
1252 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001253 self = data->self;
1254 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001255
Barry Warsawfa701a81997-01-16 00:15:11 +00001256 /* Create argument list (argv1, ..., argvN) */
1257 if (!(arg = PyTuple_New(argc - 1)))
1258 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001259
Barry Warsawfa701a81997-01-16 00:15:11 +00001260 for (i = 0; i < (argc - 1); i++) {
1261 PyObject *s = PyString_FromString(argv[i + 1]);
1262 if (!s || PyTuple_SetItem(arg, i, s)) {
1263 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001264 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001265 }
1266 }
1267 res = PyEval_CallObject(func, arg);
1268 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001269
Barry Warsawfa701a81997-01-16 00:15:11 +00001270 if (res == NULL)
1271 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001272
Barry Warsawfa701a81997-01-16 00:15:11 +00001273 if (!(tmp = PyList_New(0))) {
1274 Py_DECREF(res);
1275 return PythonCmd_Error(interp);
1276 }
1277
1278 Tcl_SetResult(Tkapp_Interp(self), AsString(res, tmp), TCL_VOLATILE);
1279 Py_DECREF(res);
1280 Py_DECREF(tmp);
1281
Guido van Rossum00d93061998-05-28 23:06:38 +00001282 LEAVE_PYTHON
1283
Barry Warsawfa701a81997-01-16 00:15:11 +00001284 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +00001285}
1286
1287static void
Fred Drake509d79a2000-07-08 04:04:38 +00001288PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001289{
Guido van Rossum00d93061998-05-28 23:06:38 +00001290 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1291
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001292 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001293 Py_XDECREF(data->self);
1294 Py_XDECREF(data->func);
1295 PyMem_DEL(data);
1296 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001297}
1298
Barry Warsawfa701a81997-01-16 00:15:11 +00001299
1300
Guido van Rossum18468821994-06-20 07:49:28 +00001301static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001302Tkapp_CreateCommand(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001303{
Guido van Rossum00d93061998-05-28 23:06:38 +00001304 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001305 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00001306 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001307 Tcl_Command err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001308
Guido van Rossum43713e52000-02-29 13:59:29 +00001309 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00001310 return NULL;
1311 if (!PyCallable_Check(func)) {
1312 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00001313 return NULL;
1314 }
Guido van Rossum18468821994-06-20 07:49:28 +00001315
Guido van Rossum00d93061998-05-28 23:06:38 +00001316 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00001317 if (!data)
1318 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001319 Py_XINCREF(self);
1320 Py_XINCREF(func);
1321 data->self = self;
1322 data->func = func;
Guido van Rossum18468821994-06-20 07:49:28 +00001323
Guido van Rossum00d93061998-05-28 23:06:38 +00001324 ENTER_TCL
1325 err = Tcl_CreateCommand(Tkapp_Interp(self), cmdName, PythonCmd,
1326 (ClientData)data, PythonCmdDelete);
1327 LEAVE_TCL
1328 if (err == NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001329 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00001330 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00001331 return NULL;
1332 }
Guido van Rossum18468821994-06-20 07:49:28 +00001333
Barry Warsawfa701a81997-01-16 00:15:11 +00001334 Py_INCREF(Py_None);
1335 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001336}
1337
Barry Warsawfa701a81997-01-16 00:15:11 +00001338
1339
Guido van Rossum18468821994-06-20 07:49:28 +00001340static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001341Tkapp_DeleteCommand(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001342{
Barry Warsawfa701a81997-01-16 00:15:11 +00001343 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00001344 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001345
Guido van Rossum43713e52000-02-29 13:59:29 +00001346 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001347 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001348 ENTER_TCL
1349 err = Tcl_DeleteCommand(Tkapp_Interp(self), cmdName);
1350 LEAVE_TCL
1351 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001352 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
1353 return NULL;
1354 }
1355 Py_INCREF(Py_None);
1356 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001357}
1358
Barry Warsawfa701a81997-01-16 00:15:11 +00001359
1360
Guido van Rossum00d93061998-05-28 23:06:38 +00001361#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00001362/** File Handler **/
1363
Guido van Rossum00d93061998-05-28 23:06:38 +00001364typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00001365 PyObject *func;
1366 PyObject *file;
1367 int id;
1368 struct _fhcdata *next;
1369} FileHandler_ClientData;
1370
1371static FileHandler_ClientData *HeadFHCD;
1372
1373static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00001374NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00001375{
1376 FileHandler_ClientData *p;
1377 p = PyMem_NEW(FileHandler_ClientData, 1);
1378 if (p != NULL) {
1379 Py_XINCREF(func);
1380 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00001381 p->func = func;
1382 p->file = file;
1383 p->id = id;
1384 p->next = HeadFHCD;
1385 HeadFHCD = p;
1386 }
1387 return p;
1388}
1389
1390static void
Fred Drake509d79a2000-07-08 04:04:38 +00001391DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00001392{
1393 FileHandler_ClientData *p, **pp;
1394
1395 pp = &HeadFHCD;
1396 while ((p = *pp) != NULL) {
1397 if (p->id == id) {
1398 *pp = p->next;
1399 Py_XDECREF(p->func);
1400 Py_XDECREF(p->file);
1401 PyMem_DEL(p);
1402 }
1403 else
1404 pp = &p->next;
1405 }
1406}
1407
Guido van Rossuma597dde1995-01-10 20:56:29 +00001408static void
Fred Drake509d79a2000-07-08 04:04:38 +00001409FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00001410{
Guido van Rossum00d93061998-05-28 23:06:38 +00001411 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001412 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00001413
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001414 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001415 func = data->func;
1416 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00001417
Barry Warsawfa701a81997-01-16 00:15:11 +00001418 arg = Py_BuildValue("(Oi)", file, (long) mask);
1419 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00001420 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00001421
1422 if (res == NULL) {
1423 errorInCmd = 1;
1424 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1425 }
1426 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001427 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001428}
1429
1430static int
Fred Drake509d79a2000-07-08 04:04:38 +00001431GetFileNo(PyObject *file)
Barry Warsawfa701a81997-01-16 00:15:11 +00001432 /* Either an int >= 0 or an object with a
1433 *.fileno() method that returns an int >= 0
1434 */
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001435{
Guido van Rossuma597dde1995-01-10 20:56:29 +00001436 PyObject *meth, *args, *res;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001437 int id;
1438 if (PyInt_Check(file)) {
1439 id = PyInt_AsLong(file);
1440 if (id < 0)
1441 PyErr_SetString(PyExc_ValueError, "invalid file id");
1442 return id;
1443 }
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001444 args = PyTuple_New(0);
1445 if (args == NULL)
1446 return -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001447
1448 meth = PyObject_GetAttrString(file, "fileno");
1449 if (meth == NULL) {
1450 Py_DECREF(args);
1451 return -1;
1452 }
1453
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001454 res = PyEval_CallObject(meth, args);
1455 Py_DECREF(args);
1456 Py_DECREF(meth);
1457 if (res == NULL)
1458 return -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001459
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001460 if (PyInt_Check(res))
1461 id = PyInt_AsLong(res);
1462 else
1463 id = -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001464
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001465 if (id < 0)
1466 PyErr_SetString(PyExc_ValueError,
1467 "invalid fileno() return value");
1468 Py_DECREF(res);
1469 return id;
Guido van Rossum18468821994-06-20 07:49:28 +00001470}
1471
1472static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001473Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
1474 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00001475{
Guido van Rossum00d93061998-05-28 23:06:38 +00001476 FileHandler_ClientData *data;
1477 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00001478 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00001479
Guido van Rossum43713e52000-02-29 13:59:29 +00001480 if (!PyArg_ParseTuple(args, "OiO:createfilehandler", &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001481 return NULL;
Guido van Rossuma80649b2000-03-28 20:07:05 +00001482 tfile = GetFileNo(file);
1483 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00001484 return NULL;
1485 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001486 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001487 return NULL;
1488 }
1489
Guido van Rossuma80649b2000-03-28 20:07:05 +00001490 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00001491 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001492 return NULL;
1493
Barry Warsawfa701a81997-01-16 00:15:11 +00001494 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00001495 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001496 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00001497 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001498 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00001499 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001500}
1501
1502static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001503Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001504{
Barry Warsawfa701a81997-01-16 00:15:11 +00001505 PyObject *file;
Guido van Rossum00d93061998-05-28 23:06:38 +00001506 FileHandler_ClientData *data;
Guido van Rossuma80649b2000-03-28 20:07:05 +00001507 int tfile;
Guido van Rossum68784361996-05-16 17:17:31 +00001508
Guido van Rossum43713e52000-02-29 13:59:29 +00001509 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00001510 return NULL;
Guido van Rossuma80649b2000-03-28 20:07:05 +00001511 tfile = GetFileNo(file);
1512 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00001513 return NULL;
1514
Guido van Rossuma80649b2000-03-28 20:07:05 +00001515 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00001516
Barry Warsawfa701a81997-01-16 00:15:11 +00001517 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00001518 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001519 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00001520 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001521 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00001522 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001523}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001524#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00001525
Barry Warsawfa701a81997-01-16 00:15:11 +00001526
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001527/**** Tktt Object (timer token) ****/
1528
1529staticforward PyTypeObject Tktt_Type;
1530
Guido van Rossum00d93061998-05-28 23:06:38 +00001531typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00001532 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00001533 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00001534 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001535} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001536
1537static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001538Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001539{
Barry Warsawfa701a81997-01-16 00:15:11 +00001540 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001541 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001542
Guido van Rossum43713e52000-02-29 13:59:29 +00001543 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00001544 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001545 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001546 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00001547 v->token = NULL;
1548 }
1549 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001550 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001551 Py_DECREF(func);
1552 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00001553 }
1554 Py_INCREF(Py_None);
1555 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001556}
1557
1558static PyMethodDef Tktt_methods[] =
1559{
Guido van Rossum35d43371997-08-02 00:09:09 +00001560 {"deletetimerhandler", Tktt_DeleteTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001561 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001562};
1563
1564static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001565Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001566{
Barry Warsawfa701a81997-01-16 00:15:11 +00001567 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001568
Guido van Rossumb18618d2000-05-03 23:44:39 +00001569 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00001570 if (v == NULL)
1571 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001572
Guido van Rossum00d93061998-05-28 23:06:38 +00001573 Py_INCREF(func);
1574 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001575 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001576
1577 /* Extra reference, deleted when called or when handler is deleted */
1578 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001579 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001580}
1581
1582static void
Fred Drake509d79a2000-07-08 04:04:38 +00001583Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001584{
Guido van Rossum00d93061998-05-28 23:06:38 +00001585 TkttObject *v = (TkttObject *)self;
1586 PyObject *func = v->func;
1587
1588 Py_XDECREF(func);
1589
Guido van Rossumb18618d2000-05-03 23:44:39 +00001590 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001591}
1592
Guido van Rossum597ac201998-05-12 14:36:19 +00001593static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001594Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001595{
Barry Warsawfa701a81997-01-16 00:15:11 +00001596 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00001597 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001598
Fred Drakea44d3532000-06-30 15:01:00 +00001599 sprintf(buf, "<tktimertoken at %p%s>", v,
Barry Warsawfa701a81997-01-16 00:15:11 +00001600 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00001601 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001602}
1603
1604static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001605Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001606{
Barry Warsawfa701a81997-01-16 00:15:11 +00001607 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001608}
1609
1610static PyTypeObject Tktt_Type =
1611{
Guido van Rossum35d43371997-08-02 00:09:09 +00001612 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001613 0, /*ob_size */
1614 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001615 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001616 0, /*tp_itemsize */
1617 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00001618 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00001619 Tktt_GetAttr, /*tp_getattr */
1620 0, /*tp_setattr */
1621 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00001622 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00001623 0, /*tp_as_number */
1624 0, /*tp_as_sequence */
1625 0, /*tp_as_mapping */
1626 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001627};
1628
Barry Warsawfa701a81997-01-16 00:15:11 +00001629
1630
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001631/** Timer Handler **/
1632
1633static void
Fred Drake509d79a2000-07-08 04:04:38 +00001634TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001635{
Guido van Rossum00d93061998-05-28 23:06:38 +00001636 TkttObject *v = (TkttObject *)clientData;
1637 PyObject *func = v->func;
1638 PyObject *res;
1639
1640 if (func == NULL)
1641 return;
1642
1643 v->func = NULL;
1644
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001645 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001646
1647 res = PyEval_CallObject(func, NULL);
1648 Py_DECREF(func);
1649 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001650
Barry Warsawfa701a81997-01-16 00:15:11 +00001651 if (res == NULL) {
1652 errorInCmd = 1;
1653 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1654 }
1655 else
1656 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001657
1658 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001659}
1660
1661static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001662Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001663{
Barry Warsawfa701a81997-01-16 00:15:11 +00001664 int milliseconds;
1665 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001666 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001667
Guido van Rossum43713e52000-02-29 13:59:29 +00001668 if (!PyArg_ParseTuple(args, "iO:createtimerhandler", &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001669 return NULL;
1670 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001671 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001672 return NULL;
1673 }
Guido van Rossum00d93061998-05-28 23:06:38 +00001674 v = Tktt_New(func);
1675 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
1676 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001677
Guido van Rossum00d93061998-05-28 23:06:38 +00001678 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001679}
1680
Barry Warsawfa701a81997-01-16 00:15:11 +00001681
Guido van Rossum18468821994-06-20 07:49:28 +00001682/** Event Loop **/
1683
Guido van Rossum18468821994-06-20 07:49:28 +00001684static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001685Tkapp_MainLoop(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001686{
Barry Warsawfa701a81997-01-16 00:15:11 +00001687 int threshold = 0;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001688#ifdef WITH_THREAD
1689 PyThreadState *tstate = PyThreadState_Get();
1690#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001691
Guido van Rossum43713e52000-02-29 13:59:29 +00001692 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00001693 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001694
Barry Warsawfa701a81997-01-16 00:15:11 +00001695 quitMainLoop = 0;
1696 while (Tk_GetNumMainWindows() > threshold &&
1697 !quitMainLoop &&
1698 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00001699 {
Guido van Rossum35d43371997-08-02 00:09:09 +00001700 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00001701
1702#ifdef WITH_THREAD
Guido van Rossum62320c91998-06-15 04:36:09 +00001703 Py_BEGIN_ALLOW_THREADS
Guido van Rossum65d5b571998-12-21 19:32:43 +00001704 PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001705 tcl_tstate = tstate;
Guido van Rossum35d43371997-08-02 00:09:09 +00001706 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001707 tcl_tstate = NULL;
Guido van Rossum65d5b571998-12-21 19:32:43 +00001708 PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00001709 if (result == 0)
1710 Sleep(20);
Guido van Rossum35d43371997-08-02 00:09:09 +00001711 Py_END_ALLOW_THREADS
Guido van Rossum5b020781997-08-19 01:00:50 +00001712#else
1713 result = Tcl_DoOneEvent(0);
1714#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001715
Guido van Rossum35d43371997-08-02 00:09:09 +00001716 if (PyErr_CheckSignals() != 0)
1717 return NULL;
1718 if (result < 0)
1719 break;
Guido van Rossum18468821994-06-20 07:49:28 +00001720 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001721 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001722
Barry Warsawfa701a81997-01-16 00:15:11 +00001723 if (errorInCmd) {
1724 errorInCmd = 0;
1725 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
1726 excInCmd = valInCmd = trbInCmd = NULL;
1727 return NULL;
1728 }
1729 Py_INCREF(Py_None);
1730 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001731}
1732
1733static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001734Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00001735{
Guido van Rossum35d43371997-08-02 00:09:09 +00001736 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00001737 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001738
Guido van Rossum43713e52000-02-29 13:59:29 +00001739 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00001740 return NULL;
1741
Guido van Rossum00d93061998-05-28 23:06:38 +00001742 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001743 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00001744 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001745 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00001746}
1747
1748static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001749Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001750{
1751
Guido van Rossum43713e52000-02-29 13:59:29 +00001752 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00001753 return NULL;
1754
1755 quitMainLoop = 1;
1756 Py_INCREF(Py_None);
1757 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001758}
1759
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001760static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001761Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001762{
1763
Guido van Rossum43713e52000-02-29 13:59:29 +00001764 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001765 return NULL;
1766
1767 return PyInt_FromLong((long)Tkapp_Interp(self));
1768}
1769
Barry Warsawfa701a81997-01-16 00:15:11 +00001770
1771
Guido van Rossum18468821994-06-20 07:49:28 +00001772/**** Tkapp Method List ****/
1773
1774static PyMethodDef Tkapp_methods[] =
1775{
Guido van Rossum35d43371997-08-02 00:09:09 +00001776 {"call", Tkapp_Call, 0},
1777 {"globalcall", Tkapp_GlobalCall, 0},
1778 {"eval", Tkapp_Eval, 1},
1779 {"globaleval", Tkapp_GlobalEval, 1},
1780 {"evalfile", Tkapp_EvalFile, 1},
1781 {"record", Tkapp_Record, 1},
1782 {"adderrorinfo", Tkapp_AddErrorInfo, 1},
1783 {"setvar", Tkapp_SetVar, 1},
1784 {"globalsetvar", Tkapp_GlobalSetVar, 1},
1785 {"getvar", Tkapp_GetVar, 1},
1786 {"globalgetvar", Tkapp_GlobalGetVar, 1},
1787 {"unsetvar", Tkapp_UnsetVar, 1},
1788 {"globalunsetvar", Tkapp_GlobalUnsetVar, 1},
1789 {"getint", Tkapp_GetInt, 1},
1790 {"getdouble", Tkapp_GetDouble, 1},
1791 {"getboolean", Tkapp_GetBoolean, 1},
1792 {"exprstring", Tkapp_ExprString, 1},
1793 {"exprlong", Tkapp_ExprLong, 1},
1794 {"exprdouble", Tkapp_ExprDouble, 1},
1795 {"exprboolean", Tkapp_ExprBoolean, 1},
1796 {"splitlist", Tkapp_SplitList, 1},
1797 {"split", Tkapp_Split, 1},
1798 {"merge", Tkapp_Merge, 0},
1799 {"createcommand", Tkapp_CreateCommand, 1},
1800 {"deletecommand", Tkapp_DeleteCommand, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001801#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001802 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1803 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001804#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001805 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001806 {"mainloop", Tkapp_MainLoop, 1},
1807 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001808 {"quit", Tkapp_Quit, 1},
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001809 {"interpaddr", Tkapp_InterpAddr, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001810 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001811};
1812
Barry Warsawfa701a81997-01-16 00:15:11 +00001813
1814
Guido van Rossum18468821994-06-20 07:49:28 +00001815/**** Tkapp Type Methods ****/
1816
1817static void
Fred Drake509d79a2000-07-08 04:04:38 +00001818Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00001819{
Guido van Rossum00d93061998-05-28 23:06:38 +00001820 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001821 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00001822 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00001823 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001824 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00001825}
1826
1827static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001828Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00001829{
Guido van Rossum35d43371997-08-02 00:09:09 +00001830 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00001831}
1832
1833static PyTypeObject Tkapp_Type =
1834{
Guido van Rossum35d43371997-08-02 00:09:09 +00001835 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001836 0, /*ob_size */
1837 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001838 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001839 0, /*tp_itemsize */
1840 Tkapp_Dealloc, /*tp_dealloc */
1841 0, /*tp_print */
1842 Tkapp_GetAttr, /*tp_getattr */
1843 0, /*tp_setattr */
1844 0, /*tp_compare */
1845 0, /*tp_repr */
1846 0, /*tp_as_number */
1847 0, /*tp_as_sequence */
1848 0, /*tp_as_mapping */
1849 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00001850};
1851
Barry Warsawfa701a81997-01-16 00:15:11 +00001852
1853
Guido van Rossum18468821994-06-20 07:49:28 +00001854/**** Tkinter Module ****/
1855
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001856typedef struct {
1857 PyObject* tuple;
1858 int size; /* current size */
1859 int maxsize; /* allocated size */
1860} FlattenContext;
1861
1862static int
1863_bump(FlattenContext* context, int size)
1864{
1865 /* expand tuple to hold (at least) size new items. return true if
1866 successful, false if an exception was raised*/
1867
1868 int maxsize = context->maxsize * 2;
1869
1870 if (maxsize < context->size + size)
1871 maxsize = context->size + size;
1872
1873 context->maxsize = maxsize;
1874
1875 return _PyTuple_Resize(&context->tuple, maxsize, 0) >= 0;
1876}
1877
1878static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001879_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001880{
1881 /* add tuple or list to argument tuple (recursively) */
1882
1883 int i, size;
1884
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001885 if (depth > 1000) {
1886 PyErr_SetString(PyExc_ValueError,"nesting too deep in _flatten");
1887 return 0;
1888 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001889 size = PyList_GET_SIZE(item);
1890 /* preallocate (assume no nesting) */
1891 if (context->size + size > context->maxsize && !_bump(context, size))
1892 return 0;
1893 /* copy items to output tuple */
1894 for (i = 0; i < size; i++) {
1895 PyObject *o = PyList_GET_ITEM(item, i);
1896 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001897 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001898 return 0;
1899 } else if (o != Py_None) {
1900 if (context->size + 1 > context->maxsize && !_bump(context, 1))
1901 return 0;
1902 Py_INCREF(o);
1903 PyTuple_SET_ITEM(context->tuple, context->size++, o);
1904 }
1905 }
1906 } else if (PyTuple_Check(item)) {
1907 /* same, for tuples */
1908 size = PyTuple_GET_SIZE(item);
1909 if (context->size + size > context->maxsize && !_bump(context, size))
1910 return 0;
1911 for (i = 0; i < size; i++) {
1912 PyObject *o = PyTuple_GET_ITEM(item, i);
1913 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001914 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001915 return 0;
1916 } else if (o != Py_None) {
1917 if (context->size + 1 > context->maxsize && !_bump(context, 1))
1918 return 0;
1919 Py_INCREF(o);
1920 PyTuple_SET_ITEM(context->tuple, context->size++, o);
1921 }
1922 }
1923 } else {
1924 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
1925 return 0;
1926 }
1927 return 1;
1928}
1929
1930static PyObject *
1931Tkinter_Flatten(PyObject* self, PyObject* args)
1932{
1933 FlattenContext context;
1934 PyObject* item;
1935
1936 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
1937 return NULL;
1938
1939 context.maxsize = PySequence_Length(item);
1940 if (context.maxsize <= 0)
1941 return PyTuple_New(0);
1942
1943 context.tuple = PyTuple_New(context.maxsize);
1944 if (!context.tuple)
1945 return NULL;
1946
1947 context.size = 0;
1948
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001949 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001950 return NULL;
1951
1952 if (_PyTuple_Resize(&context.tuple, context.size, 0))
1953 return NULL;
1954
1955 return context.tuple;
1956}
1957
Guido van Rossum18468821994-06-20 07:49:28 +00001958static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001959Tkinter_Create(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001960 PyObject *self;
1961 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001962{
Barry Warsawfa701a81997-01-16 00:15:11 +00001963 char *screenName = NULL;
1964 char *baseName = NULL;
1965 char *className = NULL;
1966 int interactive = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001967
Guido van Rossum35d43371997-08-02 00:09:09 +00001968 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00001969 if (baseName != NULL)
1970 baseName++;
1971 else
1972 baseName = Py_GetProgramName();
1973 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00001974
Guido van Rossum43713e52000-02-29 13:59:29 +00001975 if (!PyArg_ParseTuple(args, "|zssi:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00001976 &screenName, &baseName, &className,
1977 &interactive))
1978 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001979
Barry Warsawfa701a81997-01-16 00:15:11 +00001980 return (PyObject *) Tkapp_New(screenName, baseName, className,
1981 interactive);
Guido van Rossum18468821994-06-20 07:49:28 +00001982}
1983
1984static PyMethodDef moduleMethods[] =
1985{
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001986 {"_flatten", Tkinter_Flatten, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001987 {"create", Tkinter_Create, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001988#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001989 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1990 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001991#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001992 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001993 {"mainloop", Tkapp_MainLoop, 1},
1994 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001995 {"quit", Tkapp_Quit, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001996 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001997};
1998
Guido van Rossum7bf15641998-05-22 18:28:17 +00001999#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002000
2001static int stdin_ready = 0;
2002
Guido van Rossumad4db171998-06-13 13:56:28 +00002003#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002004static void
Fred Drake509d79a2000-07-08 04:04:38 +00002005MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002006{
2007 stdin_ready = 1;
2008}
Guido van Rossumad4db171998-06-13 13:56:28 +00002009#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002010
Guido van Rossum00d93061998-05-28 23:06:38 +00002011static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002012
Guido van Rossum18468821994-06-20 07:49:28 +00002013static int
Guido van Rossum35d43371997-08-02 00:09:09 +00002014EventHook()
Guido van Rossum18468821994-06-20 07:49:28 +00002015{
Guido van Rossumad4db171998-06-13 13:56:28 +00002016#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002017 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002018#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002019#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002020 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002021#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002022 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002023 errorInCmd = 0;
2024#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002025 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002026 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002027#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002028 while (!errorInCmd && !stdin_ready) {
2029 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002030#ifdef MS_WINDOWS
2031 if (_kbhit()) {
2032 stdin_ready = 1;
2033 break;
2034 }
2035#endif
2036#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002037 Py_BEGIN_ALLOW_THREADS
Guido van Rossum65d5b571998-12-21 19:32:43 +00002038 PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002039 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002040
Guido van Rossum00d93061998-05-28 23:06:38 +00002041 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002042
2043 tcl_tstate = NULL;
Guido van Rossum65d5b571998-12-21 19:32:43 +00002044 PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002045 if (result == 0)
2046 Sleep(20);
2047 Py_END_ALLOW_THREADS
2048#else
2049 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002050#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002051
2052 if (result < 0)
2053 break;
2054 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002055#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002056 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002057#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002058 if (errorInCmd) {
2059 errorInCmd = 0;
2060 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2061 excInCmd = valInCmd = trbInCmd = NULL;
2062 PyErr_Print();
2063 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002064#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002065 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002066#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002067 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002068}
Guido van Rossum18468821994-06-20 07:49:28 +00002069
Guido van Rossum00d93061998-05-28 23:06:38 +00002070#endif
2071
Guido van Rossum7bf15641998-05-22 18:28:17 +00002072static void
2073EnableEventHook()
2074{
Guido van Rossum00d93061998-05-28 23:06:38 +00002075#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002076 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002077#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002078 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002079#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002080 PyOS_InputHook = EventHook;
2081 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002082#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002083}
2084
2085static void
2086DisableEventHook()
2087{
Guido van Rossum00d93061998-05-28 23:06:38 +00002088#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002089 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2090 PyOS_InputHook = NULL;
2091 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002092#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002093}
2094
Barry Warsawfa701a81997-01-16 00:15:11 +00002095
2096/* all errors will be checked in one fell swoop in init_tkinter() */
2097static void
Fred Drake509d79a2000-07-08 04:04:38 +00002098ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002099{
2100 PyObject *v = PyInt_FromLong(val);
2101 if (v) {
2102 PyDict_SetItemString(d, name, v);
2103 Py_DECREF(v);
2104 }
2105}
2106static void
Fred Drake509d79a2000-07-08 04:04:38 +00002107ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002108{
2109 PyObject *v = PyString_FromString(val);
2110 if (v) {
2111 PyDict_SetItemString(d, name, v);
2112 Py_DECREF(v);
2113 }
2114}
2115
2116
Guido van Rossum3886bb61998-12-04 18:50:17 +00002117DL_EXPORT(void)
Guido van Rossum35d43371997-08-02 00:09:09 +00002118init_tkinter()
Guido van Rossum18468821994-06-20 07:49:28 +00002119{
Barry Warsawfa701a81997-01-16 00:15:11 +00002120 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002121
Barry Warsawfa701a81997-01-16 00:15:11 +00002122 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002123
2124#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002125 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002126#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002127
Barry Warsawfa701a81997-01-16 00:15:11 +00002128 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002129
Barry Warsawfa701a81997-01-16 00:15:11 +00002130 d = PyModule_GetDict(m);
2131 Tkinter_TclError = Py_BuildValue("s", "TclError");
2132 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002133
Guido van Rossum35d43371997-08-02 00:09:09 +00002134 ins_long(d, "READABLE", TCL_READABLE);
2135 ins_long(d, "WRITABLE", TCL_WRITABLE);
2136 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2137 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2138 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2139 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2140 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2141 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2142 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002143 ins_string(d, "TK_VERSION", TK_VERSION);
2144 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002145
Guido van Rossum83551bf1997-09-13 00:44:23 +00002146 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002147
2148 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002149 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2150
Guido van Rossume187b0e2000-03-27 21:46:29 +00002151 /* This helps the dynamic loader; in Unicode aware Tcl versions
2152 it also helps Tcl find its encodings. */
2153 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00002154
Barry Warsawfa701a81997-01-16 00:15:11 +00002155 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002156 return;
2157
Guido van Rossum43ff8681998-07-14 18:02:13 +00002158#if 0
2159 /* This was not a good idea; through <Destroy> bindings,
2160 Tcl_Finalize() may invoke Python code but at that point the
2161 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002162 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002163#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002164
Jack Jansen34cc5c31995-10-31 16:15:12 +00002165#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002166 /*
2167 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2168 ** Most of the initializations in that routine (toolbox init calls and
2169 ** such) have already been done for us, so we only need these.
2170 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002171 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002172
2173 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00002174#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00002175 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00002176#endif /* GENERATINGCFM */
2177#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00002178}
Guido van Rossum9722ad81995-09-22 23:49:28 +00002179
Guido van Rossumec22c921996-02-25 04:50:29 +00002180
Barry Warsawfa701a81997-01-16 00:15:11 +00002181
Guido van Rossum9722ad81995-09-22 23:49:28 +00002182#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002183
2184/*
Guido van Rossumec22c921996-02-25 04:50:29 +00002185** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002186*/
2187
Guido van Rossum9722ad81995-09-22 23:49:28 +00002188void
2189panic(char * format, ...)
2190{
Barry Warsawfa701a81997-01-16 00:15:11 +00002191 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002192
Barry Warsawfa701a81997-01-16 00:15:11 +00002193 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002194
Guido van Rossum227cf761998-08-05 13:53:32 +00002195 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002196 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002197
Barry Warsawfa701a81997-01-16 00:15:11 +00002198 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002199
Barry Warsawfa701a81997-01-16 00:15:11 +00002200 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00002201}
Jack Jansen40b546d1995-11-14 10:34:45 +00002202
Guido van Rossumec22c921996-02-25 04:50:29 +00002203/*
2204** Pass events to SIOUX before passing them to Tk.
2205*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002206
Guido van Rossumec22c921996-02-25 04:50:29 +00002207static int
Fred Drake509d79a2000-07-08 04:04:38 +00002208PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002209{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002210 WindowPtr frontwin;
2211 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00002212 ** Sioux eats too many events, so we don't pass it everything. We
2213 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002214 ** the Sioux window is frontmost. This means that Tk menus don't work
2215 ** in that case, but at least we can scroll the sioux window.
2216 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2217 ** part of the external interface of Sioux...
2218 */
2219 frontwin = FrontWindow();
2220 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
2221 if (SIOUXHandleOneEvent(eventPtr))
2222 return 0; /* Nothing happened to the Tcl event queue */
2223 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002224 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002225}
2226
Guido van Rossumec22c921996-02-25 04:50:29 +00002227#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002228
2229/*
2230** Additional Mac specific code for dealing with shared libraries.
2231*/
2232
2233#include <Resources.h>
2234#include <CodeFragments.h>
2235
2236static int loaded_from_shlib = 0;
2237static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002238
Jack Jansen34cc5c31995-10-31 16:15:12 +00002239/*
2240** If this module is dynamically loaded the following routine should
2241** be the init routine. It takes care of adding the shared library to
2242** the resource-file chain, so that the tk routines can find their
2243** resources.
2244*/
2245OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002246init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002247{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00002248 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00002249 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002250 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002251 library_fss = *data->fragLocator.u.onDisk.fileSpec;
2252 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002253 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002254 library_fss = *data->fragLocator.u.inSegs.fileSpec;
2255 loaded_from_shlib = 1;
2256 }
2257 return noErr;
2258}
2259
2260/*
2261** Insert the library resources into the search path. Put them after
2262** the resources from the application. Again, we ignore errors.
2263*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002264static
Jack Jansen34cc5c31995-10-31 16:15:12 +00002265mac_addlibresources()
2266{
2267 if ( !loaded_from_shlib )
2268 return;
2269 (void)FSpOpenResFile(&library_fss, fsRdPerm);
2270}
2271
Guido van Rossumec22c921996-02-25 04:50:29 +00002272#endif /* GENERATINGCFM */
2273#endif /* macintosh */